Commit b86f0aaae2f0212bc01ddfd3e5d646c22eb1d8c0
Committed by
Gitee
!28 语音对讲合并
语音对讲合并
Showing
81 changed files
with
7312 additions
and
3865 deletions
README.md
| ... | ... | @@ -134,3 +134,11 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git |
| 134 | 134 | [mk1990](https://github.com/mk1990) [SaltFish001](https://github.com/SaltFish001) |
| 135 | 135 | |
| 136 | 136 | |
| 137 | +ffmpeg -re -i 123.mp3 -acodec pcm_alaw -ar 8000 -ac 1 -f rtsp rtsp://192.168.1.3:30554/broadcast/34020000001320000101_34020000001310000001 | |
| 138 | + | |
| 139 | +ffmpeg -re -i 123.mp3 -acodec pcm_alaw -ar 8000 -ac 1 -f rtsp rtsp://192.168.1.3:30554/talk/34020000001320000011_34020000001370000001 | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | +ffmpeg -re -i 123.mp3 -acodec pcm_alaw -ar 8000 -ac 1 -f rtsp rtsp://192.168.1.3:30554/talk/34020000001320000101_34020000001310000001 | |
| 144 | + | ... | ... |
doc/README.md
doc/_content/broadcast.md
0 → 100644
| 1 | +# 原理图 | |
| 2 | + | |
| 3 | +## 使用ffmpeg测试语音对讲原理 | |
| 4 | +```plantuml | |
| 5 | +@startuml | |
| 6 | +"FFMPEG" -> "ZLMediaKit": 推流到zlm | |
| 7 | +"WVP-PRO" <- "ZLMediaKit": 通知收到语音对讲推流,携带设备和通道信息 | |
| 8 | +"WVP-PRO" -> "设备": 开始语音对讲 | |
| 9 | +"WVP-PRO" <-- "设备": 语音对讲建立成功,携带收流端口 | |
| 10 | +"WVP-PRO" -> "ZLMediaKit": 通知zlm将流推送到设备收流端口 | |
| 11 | +"ZLMediaKit" -> "设备": 向设备推流 | |
| 12 | +@enduml | |
| 13 | +``` | |
| 14 | + | |
| 15 | +## 使用网页测试语音对讲原理 | |
| 16 | +```plantuml | |
| 17 | +@startuml | |
| 18 | +"前端页面" -> "WVP-PRO": 请求推流地址 | |
| 19 | +"前端页面" <-- "WVP-PRO": 返回推流地址 | |
| 20 | +"前端页面" -> "ZLMediaKit": 使用webrtc推流到zlm,以下过程相同 | |
| 21 | +"WVP-PRO" <- "ZLMediaKit": 通知收到语音对讲推流,携带设备和通道信息 | |
| 22 | +"WVP-PRO" -> "设备": 开始语音对讲 | |
| 23 | +"WVP-PRO" <-- "设备": 语音对讲建立成功,携带收流端口 | |
| 24 | +"WVP-PRO" -> "ZLMediaKit": 通知zlm将流推送到设备收流端口 | |
| 25 | +"ZLMediaKit" -> "设备": 向设备推流 | |
| 26 | +@enduml | |
| 27 | +``` | |
| 0 | 28 | \ No newline at end of file | ... | ... |
doc/_content/introduction/deployment.md
| ... | ... | @@ -21,9 +21,9 @@ |
| 21 | 21 | 4. WVP-PRO与ZLM支持分开部署,但是wvp-pro-assist必须与zlm部署在同一台主机; |
| 22 | 22 | 5. 生产环境按需开放端口,但是建议修改默认端口,尤其是5060端口,易受到攻击; |
| 23 | 23 | 6. zlm使用docker部署的情况,要求端口映射一致,比如映射5060,应将外部端口也映射为5060端口; |
| 24 | -7. 启动服务,以linux为例 | |
| 25 | -### 启动WVP-PRO | |
| 26 | -**jar包:** | |
| 24 | +7. zlm与wvp会保持高频率的通信,所以不要去将wvp与zlm分属在两个网络,比如wvp在内网,zlm却在公网的情况。 | |
| 25 | +8. 启动服务,以linux为例 | |
| 26 | +**启动WVP-PRO** | |
| 27 | 27 | ```shell |
| 28 | 28 | nohup java -jar wvp-pro-*.jar & |
| 29 | 29 | ``` | ... | ... |
doc/_content/theory/broadcast_cascade.md
0 → 100644
| 1 | +<!-- 点播流程 --> | |
| 2 | + | |
| 3 | +# 点播流程 | |
| 4 | +> 以下为WVP-PRO级联语音喊话流程。 | |
| 5 | + | |
| 6 | +```plantuml | |
| 7 | +@startuml | |
| 8 | +"上级平台" -> "下级平台": 1. 发起语音喊话请求 | |
| 9 | +"上级平台" <-- "下级平台": 2. 200OK | |
| 10 | +"上级平台" <- "下级平台": 3. 回复Result OK | |
| 11 | +"上级平台" --> "下级平台": 4. 200OK | |
| 12 | + | |
| 13 | +"下级平台" -> "设备": 5. 发起语音喊话请求 | |
| 14 | +"下级平台" <-- "设备": 6. 200OK | |
| 15 | +"下级平台" <- "设备": 7. 回复Result OK | |
| 16 | +"下级平台" --> "设备": 8. 200OK | |
| 17 | + | |
| 18 | +"下级平台" <- "设备": 9. invite(broadcast) | |
| 19 | +"下级平台" --> "设备": 10. 100 trying | |
| 20 | +"下级平台" --> "设备": 11. 200OK SDP | |
| 21 | +"下级平台" <-- "设备": 12. ack | |
| 22 | + | |
| 23 | +"上级平台" <- "下级平台": 13. invite(broadcast) | |
| 24 | +"上级平台" --> "下级平台": 14. 100 trying | |
| 25 | +"上级平台" --> "下级平台": 15. 200OK SDP | |
| 26 | +"上级平台" <-- "下级平台": 16. ack | |
| 27 | + | |
| 28 | +"上级平台" -> "下级平台": 17. 推送RTP | |
| 29 | +"下级平台" -> "设备": 18. 推送RTP | |
| 30 | + | |
| 31 | +@enduml | |
| 32 | +``` | |
| 33 | + | |
| 34 | + | |
| 35 | +## 注册流程描述如下: | |
| 36 | +1. 用户从网页或调用接口发起点播请求; | |
| 37 | +2. WVP-PRO向摄像机发送Invite消息,消息头域中携带 Subject字段,表明点播的视频源ID、发送方媒体流序列号、ZLMediaKit接收流使用的IP、端口号、 | |
| 38 | + 接收端媒体流序列号等参数,SDP消息体中 s字段为“Play”代表实时点播,y字段描述SSRC值,f字段描述媒体参数。 | |
| 39 | +3. 摄像机向WVP-PRO回复200OK,消息体中描述了媒体流发送者发送媒体流的IP、端口、媒体格式、SSRC字段等内容。 | |
| 40 | +4. WVP-PRO向设备回复Ack, 会话建立成功。 | |
| 41 | +5. 设备向ZLMediaKit发送实时流。 | |
| 42 | +6. ZLMediaKit向WVP-PRO发送流改变事件。 | |
| 43 | +7. WVP-PRO向WEB用户回复播放地址。 | |
| 44 | +8. ZLMediaKit向WVP发送流无人观看事件。 | |
| 45 | +9. WVP-PRO向设备回复Bye, 结束会话。 | |
| 46 | +10. 设备回复200OK,会话结束成功。 | ... | ... |
doc/_sidebar.md
src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
| ... | ... | @@ -240,11 +240,11 @@ public class StreamInfo implements Serializable, Cloneable{ |
| 240 | 240 | } |
| 241 | 241 | } |
| 242 | 242 | |
| 243 | - public void setRtc(String host, int port, int sslPort, String app, String stream, String callIdParam) { | |
| 243 | + public void setRtc(String host, int port, int sslPort, String app, String stream, String callIdParam, boolean isPlay) { | |
| 244 | 244 | if (callIdParam != null) { |
| 245 | 245 | callIdParam = Objects.equals(callIdParam, "") ? callIdParam : callIdParam.replace("?", "&"); |
| 246 | 246 | } |
| 247 | - String file = String.format("index/api/webrtc?app=%s&stream=%s&type=play%s", app, stream, callIdParam); | |
| 247 | + String file = String.format("index/api/webrtc?app=%s&stream=%s&type=%s%s", app, stream, isPlay?"play":"push", callIdParam); | |
| 248 | 248 | if (port > 0) { |
| 249 | 249 | this.rtc = new StreamURL("http", host, port, file); |
| 250 | 250 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
| ... | ... | @@ -68,6 +68,7 @@ public class VideoManagerConstants { |
| 68 | 68 | public static final String SYSTEM_INFO_NET_PREFIX = "VMP_SYSTEM_INFO_NET_"; |
| 69 | 69 | |
| 70 | 70 | public static final String SYSTEM_INFO_DISK_PREFIX = "VMP_SYSTEM_INFO_DISK_"; |
| 71 | + public static final String BROADCAST_WAITE_INVITE = "task_broadcast_waite_invite_"; | |
| 71 | 72 | |
| 72 | 73 | public static final String REGISTER_EXPIRE_TASK_KEY_PREFIX = "VMP_device_register_expire_"; |
| 73 | 74 | public static final String PUSH_STREAM_LIST = "VMP_PUSH_STREAM_LIST_"; | ... | ... |
src/main/java/com/genersoft/iot/vmp/conf/GlobalResponseAdvice.java
| ... | ... | @@ -32,7 +32,7 @@ public class GlobalResponseAdvice implements ResponseBodyAdvice<Object> { |
| 32 | 32 | @Override |
| 33 | 33 | public Object beforeBodyWrite(Object body, @NotNull MethodParameter returnType, @NotNull MediaType selectedContentType, @NotNull Class<? extends HttpMessageConverter<?>> selectedConverterType, @NotNull ServerHttpRequest request, @NotNull ServerHttpResponse response) { |
| 34 | 34 | // 排除api文档的接口,这个接口不需要统一 |
| 35 | - String[] excludePath = {"/v3/api-docs","/api/v1","/index/hook"}; | |
| 35 | + String[] excludePath = {"/v3/api-docs","/api/v1","/index/hook","/api/video-"}; | |
| 36 | 36 | for (String path : excludePath) { |
| 37 | 37 | if (request.getURI().getPath().startsWith(path)) { |
| 38 | 38 | return body; |
| ... | ... | @@ -59,8 +59,8 @@ public class GlobalResponseAdvice implements ResponseBodyAdvice<Object> { |
| 59 | 59 | * 防止返回string时出错 |
| 60 | 60 | * @return |
| 61 | 61 | */ |
| 62 | - @Bean | |
| 63 | - public HttpMessageConverters fast() { | |
| 62 | + /*@Bean | |
| 63 | + public HttpMessageConverters custHttpMessageConverter() { | |
| 64 | 64 | return new HttpMessageConverters(new FastJsonHttpMessageConverter()); |
| 65 | - } | |
| 65 | + }*/ | |
| 66 | 66 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java
src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java
| ... | ... | @@ -33,7 +33,7 @@ public class UserSetting { |
| 33 | 33 | |
| 34 | 34 | private Boolean logInDatabase = Boolean.TRUE; |
| 35 | 35 | |
| 36 | - private Boolean usePushingAsStatus = Boolean.TRUE; | |
| 36 | + private Boolean usePushingAsStatus = Boolean.FALSE; | |
| 37 | 37 | |
| 38 | 38 | private Boolean useSourceIpAsStreamIp = Boolean.FALSE; |
| 39 | 39 | |
| ... | ... | @@ -58,6 +58,8 @@ public class UserSetting { |
| 58 | 58 | |
| 59 | 59 | private String thirdPartyGBIdReg = "[\\s\\S]*"; |
| 60 | 60 | |
| 61 | + private String broadcastForPlatform = "UDP"; | |
| 62 | + | |
| 61 | 63 | private String civilCodeFile = "classpath:civilCode.csv"; |
| 62 | 64 | |
| 63 | 65 | private List<String> interfaceAuthenticationExcludes = new ArrayList<>(); |
| ... | ... | @@ -210,6 +212,14 @@ public class UserSetting { |
| 210 | 212 | this.syncChannelOnDeviceOnline = syncChannelOnDeviceOnline; |
| 211 | 213 | } |
| 212 | 214 | |
| 215 | + public String getBroadcastForPlatform() { | |
| 216 | + return broadcastForPlatform; | |
| 217 | + } | |
| 218 | + | |
| 219 | + public void setBroadcastForPlatform(String broadcastForPlatform) { | |
| 220 | + this.broadcastForPlatform = broadcastForPlatform; | |
| 221 | + } | |
| 222 | + | |
| 213 | 223 | public Boolean getSipUseSourceIpAsRemoteAddress() { |
| 214 | 224 | return sipUseSourceIpAsRemoteAddress; |
| 215 | 225 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/conf/redis/RedisConfig.java
0 → 100644
src/main/java/com/genersoft/iot/vmp/conf/security/dto/LoginUser.java
| ... | ... | @@ -100,6 +100,9 @@ public class LoginUser implements UserDetails, CredentialsContainer { |
| 100 | 100 | return user.getRole(); |
| 101 | 101 | } |
| 102 | 102 | |
| 103 | + public String getPushKey() { | |
| 104 | + return user.getPushKey(); | |
| 105 | + } | |
| 103 | 106 | |
| 104 | 107 | public String getAccessToken() { |
| 105 | 108 | return accessToken; | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/AudioBroadcastCatch.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.gb28181.bean; | |
| 2 | + | |
| 3 | + | |
| 4 | +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | |
| 5 | +import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioBroadcastEvent; | |
| 6 | +import gov.nist.javax.sip.message.SIPResponse; | |
| 7 | + | |
| 8 | +/** | |
| 9 | + * 缓存语音广播的状态 | |
| 10 | + * @author lin | |
| 11 | + */ | |
| 12 | +public class AudioBroadcastCatch { | |
| 13 | + | |
| 14 | + | |
| 15 | + public AudioBroadcastCatch( | |
| 16 | + String deviceId, | |
| 17 | + String channelId, | |
| 18 | + MediaServerItem mediaServerItem, | |
| 19 | + String app, | |
| 20 | + String stream, | |
| 21 | + AudioBroadcastEvent event, | |
| 22 | + AudioBroadcastCatchStatus status, | |
| 23 | + boolean isFromPlatform | |
| 24 | + ) { | |
| 25 | + this.deviceId = deviceId; | |
| 26 | + this.channelId = channelId; | |
| 27 | + this.status = status; | |
| 28 | + this.event = event; | |
| 29 | + this.isFromPlatform = isFromPlatform; | |
| 30 | + this.app = app; | |
| 31 | + this.stream = stream; | |
| 32 | + this.mediaServerItem = mediaServerItem; | |
| 33 | + } | |
| 34 | + | |
| 35 | + public AudioBroadcastCatch() { | |
| 36 | + } | |
| 37 | + | |
| 38 | + /** | |
| 39 | + * 设备编号 | |
| 40 | + */ | |
| 41 | + private String deviceId; | |
| 42 | + | |
| 43 | + /** | |
| 44 | + * 通道编号 | |
| 45 | + */ | |
| 46 | + private String channelId; | |
| 47 | + | |
| 48 | + /** | |
| 49 | + * 流媒体信息 | |
| 50 | + */ | |
| 51 | + private MediaServerItem mediaServerItem; | |
| 52 | + | |
| 53 | + /** | |
| 54 | + * 关联的流APP | |
| 55 | + */ | |
| 56 | + private String app; | |
| 57 | + | |
| 58 | + /** | |
| 59 | + * 关联的流STREAM | |
| 60 | + */ | |
| 61 | + private String stream; | |
| 62 | + | |
| 63 | + /** | |
| 64 | + * 是否是级联语音喊话 | |
| 65 | + */ | |
| 66 | + private boolean isFromPlatform; | |
| 67 | + | |
| 68 | + /** | |
| 69 | + * 语音广播状态 | |
| 70 | + */ | |
| 71 | + private AudioBroadcastCatchStatus status; | |
| 72 | + | |
| 73 | + /** | |
| 74 | + * 请求信息 | |
| 75 | + */ | |
| 76 | + private SipTransactionInfo sipTransactionInfo; | |
| 77 | + | |
| 78 | + /** | |
| 79 | + * 请求结果回调 | |
| 80 | + */ | |
| 81 | + private AudioBroadcastEvent event; | |
| 82 | + | |
| 83 | + | |
| 84 | + public String getDeviceId() { | |
| 85 | + return deviceId; | |
| 86 | + } | |
| 87 | + | |
| 88 | + public void setDeviceId(String deviceId) { | |
| 89 | + this.deviceId = deviceId; | |
| 90 | + } | |
| 91 | + | |
| 92 | + public String getChannelId() { | |
| 93 | + return channelId; | |
| 94 | + } | |
| 95 | + | |
| 96 | + public void setChannelId(String channelId) { | |
| 97 | + this.channelId = channelId; | |
| 98 | + } | |
| 99 | + | |
| 100 | + public AudioBroadcastCatchStatus getStatus() { | |
| 101 | + return status; | |
| 102 | + } | |
| 103 | + | |
| 104 | + public void setStatus(AudioBroadcastCatchStatus status) { | |
| 105 | + this.status = status; | |
| 106 | + } | |
| 107 | + | |
| 108 | + public SipTransactionInfo getSipTransactionInfo() { | |
| 109 | + return sipTransactionInfo; | |
| 110 | + } | |
| 111 | + | |
| 112 | + public MediaServerItem getMediaServerItem() { | |
| 113 | + return mediaServerItem; | |
| 114 | + } | |
| 115 | + | |
| 116 | + public void setMediaServerItem(MediaServerItem mediaServerItem) { | |
| 117 | + this.mediaServerItem = mediaServerItem; | |
| 118 | + } | |
| 119 | + | |
| 120 | + public String getApp() { | |
| 121 | + return app; | |
| 122 | + } | |
| 123 | + | |
| 124 | + public void setApp(String app) { | |
| 125 | + this.app = app; | |
| 126 | + } | |
| 127 | + | |
| 128 | + public String getStream() { | |
| 129 | + return stream; | |
| 130 | + } | |
| 131 | + | |
| 132 | + public void setStream(String stream) { | |
| 133 | + this.stream = stream; | |
| 134 | + } | |
| 135 | + | |
| 136 | + public boolean isFromPlatform() { | |
| 137 | + return isFromPlatform; | |
| 138 | + } | |
| 139 | + | |
| 140 | + public void setFromPlatform(boolean fromPlatform) { | |
| 141 | + isFromPlatform = fromPlatform; | |
| 142 | + } | |
| 143 | + | |
| 144 | + public void setSipTransactionInfo(SipTransactionInfo sipTransactionInfo) { | |
| 145 | + this.sipTransactionInfo = sipTransactionInfo; | |
| 146 | + } | |
| 147 | + | |
| 148 | + public AudioBroadcastEvent getEvent() { | |
| 149 | + return event; | |
| 150 | + } | |
| 151 | + | |
| 152 | + public void setEvent(AudioBroadcastEvent event) { | |
| 153 | + this.event = event; | |
| 154 | + } | |
| 155 | + | |
| 156 | + public void setSipTransactionInfoByRequset(SIPResponse sipResponse) { | |
| 157 | + this.sipTransactionInfo = new SipTransactionInfo(sipResponse); | |
| 158 | + } | |
| 159 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/AudioBroadcastCatchStatus.java
0 → 100644
src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java
| ... | ... | @@ -188,8 +188,8 @@ public class Device { |
| 188 | 188 | @Schema(description = "设备注册的事务信息") |
| 189 | 189 | private SipTransactionInfo sipTransactionInfo; |
| 190 | 190 | |
| 191 | - | |
| 192 | - | |
| 191 | + @Schema(description = "控制语音对讲流程,释放收到ACK后发流") | |
| 192 | + private boolean broadcastPushAfterAck; | |
| 193 | 193 | |
| 194 | 194 | public String getDeviceId() { |
| 195 | 195 | return deviceId; |
| ... | ... | @@ -452,5 +452,11 @@ public class Device { |
| 452 | 452 | public void setSipTransactionInfo(SipTransactionInfo sipTransactionInfo) { |
| 453 | 453 | this.sipTransactionInfo = sipTransactionInfo; |
| 454 | 454 | } |
| 455 | + public boolean isBroadcastPushAfterAck() { | |
| 456 | + return broadcastPushAfterAck; | |
| 457 | + } | |
| 455 | 458 | |
| 459 | + public void setBroadcastPushAfterAck(boolean broadcastPushAfterAck) { | |
| 460 | + this.broadcastPushAfterAck = broadcastPushAfterAck; | |
| 461 | + } | |
| 456 | 462 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteStreamType.java
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java
| ... | ... | @@ -66,7 +66,7 @@ public class ParentPlatform { |
| 66 | 66 | * 设备端口 |
| 67 | 67 | */ |
| 68 | 68 | @Schema(description = "设备端口") |
| 69 | - private String devicePort; | |
| 69 | + private int devicePort; | |
| 70 | 70 | |
| 71 | 71 | /** |
| 72 | 72 | * SIP认证用户名(默认使用设备国标编号) |
| ... | ... | @@ -261,11 +261,11 @@ public class ParentPlatform { |
| 261 | 261 | this.deviceIp = deviceIp; |
| 262 | 262 | } |
| 263 | 263 | |
| 264 | - public String getDevicePort() { | |
| 264 | + public int getDevicePort() { | |
| 265 | 265 | return devicePort; |
| 266 | 266 | } |
| 267 | 267 | |
| 268 | - public void setDevicePort(String devicePort) { | |
| 268 | + public void setDevicePort(int devicePort) { | |
| 269 | 269 | this.devicePort = devicePort; |
| 270 | 270 | } |
| 271 | 271 | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java
| ... | ... | @@ -49,7 +49,7 @@ public class SendRtpItem { |
| 49 | 49 | /** |
| 50 | 50 | * 设备推流的streamId |
| 51 | 51 | */ |
| 52 | - private String streamId; | |
| 52 | + private String stream; | |
| 53 | 53 | |
| 54 | 54 | /** |
| 55 | 55 | * 是否为tcp |
| ... | ... | @@ -117,6 +117,11 @@ public class SendRtpItem { |
| 117 | 117 | */ |
| 118 | 118 | private InviteStreamType playType; |
| 119 | 119 | |
| 120 | + /** | |
| 121 | + * 发流的同时收流 | |
| 122 | + */ | |
| 123 | + private String receiveStream; | |
| 124 | + | |
| 120 | 125 | public String getIp() { |
| 121 | 126 | return ip; |
| 122 | 127 | } |
| ... | ... | @@ -181,12 +186,12 @@ public class SendRtpItem { |
| 181 | 186 | this.app = app; |
| 182 | 187 | } |
| 183 | 188 | |
| 184 | - public String getStreamId() { | |
| 185 | - return streamId; | |
| 189 | + public String getStream() { | |
| 190 | + return stream; | |
| 186 | 191 | } |
| 187 | 192 | |
| 188 | - public void setStreamId(String streamId) { | |
| 189 | - this.streamId = streamId; | |
| 193 | + public void setStream(String stream) { | |
| 194 | + this.stream = stream; | |
| 190 | 195 | } |
| 191 | 196 | |
| 192 | 197 | public boolean isTcp() { |
| ... | ... | @@ -292,4 +297,12 @@ public class SendRtpItem { |
| 292 | 297 | public void setRtcp(boolean rtcp) { |
| 293 | 298 | this.rtcp = rtcp; |
| 294 | 299 | } |
| 300 | + | |
| 301 | + public String getReceiveStream() { | |
| 302 | + return receiveStream; | |
| 303 | + } | |
| 304 | + | |
| 305 | + public void setReceiveStream(String receiveStream) { | |
| 306 | + this.receiveStream = receiveStream; | |
| 307 | + } | |
| 295 | 308 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SipTransactionInfo.java
| 1 | 1 | package com.genersoft.iot.vmp.gb28181.bean; |
| 2 | 2 | |
| 3 | -import gov.nist.javax.sip.message.SIPRequest; | |
| 4 | 3 | import gov.nist.javax.sip.message.SIPResponse; |
| 5 | 4 | |
| 6 | 5 | public class SipTransactionInfo { |
| ... | ... | @@ -10,11 +9,23 @@ public class SipTransactionInfo { |
| 10 | 9 | private String toTag; |
| 11 | 10 | private String viaBranch; |
| 12 | 11 | |
| 12 | + // 自己是否媒体流发送者 | |
| 13 | + private boolean asSender; | |
| 14 | + | |
| 15 | + public SipTransactionInfo(SIPResponse response, boolean asSender) { | |
| 16 | + this.callId = response.getCallIdHeader().getCallId(); | |
| 17 | + this.fromTag = response.getFromTag(); | |
| 18 | + this.toTag = response.getToTag(); | |
| 19 | + this.viaBranch = response.getTopmostViaHeader().getBranch(); | |
| 20 | + this.asSender = asSender; | |
| 21 | + } | |
| 22 | + | |
| 13 | 23 | public SipTransactionInfo(SIPResponse response) { |
| 14 | 24 | this.callId = response.getCallIdHeader().getCallId(); |
| 15 | 25 | this.fromTag = response.getFromTag(); |
| 16 | 26 | this.toTag = response.getToTag(); |
| 17 | 27 | this.viaBranch = response.getTopmostViaHeader().getBranch(); |
| 28 | + this.asSender = false; | |
| 18 | 29 | } |
| 19 | 30 | |
| 20 | 31 | public SipTransactionInfo() { |
| ... | ... | @@ -51,4 +62,12 @@ public class SipTransactionInfo { |
| 51 | 62 | public void setViaBranch(String viaBranch) { |
| 52 | 63 | this.viaBranch = viaBranch; |
| 53 | 64 | } |
| 65 | + | |
| 66 | + public boolean isAsSender() { | |
| 67 | + return asSender; | |
| 68 | + } | |
| 69 | + | |
| 70 | + public void setAsSender(boolean asSender) { | |
| 71 | + this.asSender = asSender; | |
| 72 | + } | |
| 54 | 73 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java
| ... | ... | @@ -61,7 +61,7 @@ public class SipSubscribe { |
| 61 | 61 | logger.debug("errorSubscribes.size:{}",errorSubscribes.size()); |
| 62 | 62 | } |
| 63 | 63 | |
| 64 | - public interface Event { void response(EventResult eventResult) ; | |
| 64 | + public interface Event { void response(EventResult eventResult); | |
| 65 | 65 | } |
| 66 | 66 | |
| 67 | 67 | /** |
| ... | ... | @@ -78,8 +78,10 @@ public class SipSubscribe { |
| 78 | 78 | dialogTerminated, |
| 79 | 79 | // 设备未找到 |
| 80 | 80 | deviceNotFoundEvent, |
| 81 | - // 设备未找到 | |
| 82 | - cmdSendFailEvent | |
| 81 | + // 消息发送失败 | |
| 82 | + cmdSendFailEvent, | |
| 83 | + // 消息发送失败 | |
| 84 | + failedToGetPort | |
| 83 | 85 | } |
| 84 | 86 | |
| 85 | 87 | public static class EventResult<EventObject>{ | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/session/AudioBroadcastManager.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.gb28181.session; | |
| 2 | + | |
| 3 | +import com.genersoft.iot.vmp.conf.SipConfig; | |
| 4 | +import com.genersoft.iot.vmp.gb28181.bean.AudioBroadcastCatch; | |
| 5 | +import com.genersoft.iot.vmp.gb28181.utils.SipUtils; | |
| 6 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 7 | +import org.springframework.stereotype.Component; | |
| 8 | + | |
| 9 | +import java.util.*; | |
| 10 | +import java.util.concurrent.ConcurrentHashMap; | |
| 11 | +import java.util.stream.Collectors; | |
| 12 | +import java.util.stream.Stream; | |
| 13 | + | |
| 14 | +/** | |
| 15 | + * 语音广播消息管理类 | |
| 16 | + * @author lin | |
| 17 | + */ | |
| 18 | +@Component | |
| 19 | +public class AudioBroadcastManager { | |
| 20 | + | |
| 21 | + @Autowired | |
| 22 | + private SipConfig config; | |
| 23 | + | |
| 24 | + public static Map<String, AudioBroadcastCatch> data = new ConcurrentHashMap<>(); | |
| 25 | + | |
| 26 | + public void update(AudioBroadcastCatch audioBroadcastCatch) { | |
| 27 | + if (SipUtils.isFrontEnd(audioBroadcastCatch.getDeviceId())) { | |
| 28 | + data.put(audioBroadcastCatch.getDeviceId(), audioBroadcastCatch); | |
| 29 | + }else { | |
| 30 | + data.put(audioBroadcastCatch.getDeviceId() + audioBroadcastCatch.getChannelId(), audioBroadcastCatch); | |
| 31 | + } | |
| 32 | + } | |
| 33 | + | |
| 34 | + public void del(String deviceId, String channelId) { | |
| 35 | + if (SipUtils.isFrontEnd(deviceId)) { | |
| 36 | + data.remove(deviceId); | |
| 37 | + }else { | |
| 38 | + data.remove(deviceId + channelId); | |
| 39 | + } | |
| 40 | + | |
| 41 | + } | |
| 42 | + | |
| 43 | + public void delByDeviceId(String deviceId) { | |
| 44 | + for (String key : data.keySet()) { | |
| 45 | + if (key.startsWith(deviceId)) { | |
| 46 | + data.remove(key); | |
| 47 | + } | |
| 48 | + } | |
| 49 | + } | |
| 50 | + | |
| 51 | + public List<AudioBroadcastCatch> getAll(){ | |
| 52 | + Collection<AudioBroadcastCatch> values = data.values(); | |
| 53 | + return new ArrayList<>(values); | |
| 54 | + } | |
| 55 | + | |
| 56 | + | |
| 57 | + public boolean exit(String deviceId, String channelId) { | |
| 58 | + for (String key : data.keySet()) { | |
| 59 | + if (SipUtils.isFrontEnd(deviceId)) { | |
| 60 | + return key.equals(deviceId); | |
| 61 | + }else { | |
| 62 | + return key.equals(deviceId + channelId); | |
| 63 | + } | |
| 64 | + } | |
| 65 | + return false; | |
| 66 | + } | |
| 67 | + | |
| 68 | + public AudioBroadcastCatch get(String deviceId, String channelId) { | |
| 69 | + AudioBroadcastCatch audioBroadcastCatch; | |
| 70 | + if (SipUtils.isFrontEnd(deviceId)) { | |
| 71 | + audioBroadcastCatch = data.get(deviceId); | |
| 72 | + }else { | |
| 73 | + audioBroadcastCatch = data.get(deviceId + channelId); | |
| 74 | + } | |
| 75 | + if (audioBroadcastCatch == null) { | |
| 76 | + Stream<AudioBroadcastCatch> allAudioBroadcastCatchStreamForDevice = data.values().stream().filter( | |
| 77 | + audioBroadcastCatchItem -> Objects.equals(audioBroadcastCatchItem.getDeviceId(), deviceId)); | |
| 78 | + List<AudioBroadcastCatch> audioBroadcastCatchList = allAudioBroadcastCatchStreamForDevice.collect(Collectors.toList()); | |
| 79 | + if (audioBroadcastCatchList.size() == 1 && Objects.equals(config.getId(), channelId)) { | |
| 80 | + audioBroadcastCatch = audioBroadcastCatchList.get(0); | |
| 81 | + } | |
| 82 | + } | |
| 83 | + | |
| 84 | + return audioBroadcastCatch; | |
| 85 | + } | |
| 86 | + | |
| 87 | + public List<AudioBroadcastCatch> get(String deviceId) { | |
| 88 | + List<AudioBroadcastCatch> audioBroadcastCatchList= new ArrayList<>(); | |
| 89 | + if (SipUtils.isFrontEnd(deviceId)) { | |
| 90 | + if (data.get(deviceId) != null) { | |
| 91 | + audioBroadcastCatchList.add(data.get(deviceId)); | |
| 92 | + } | |
| 93 | + }else { | |
| 94 | + for (String key : data.keySet()) { | |
| 95 | + if (key.startsWith(deviceId)) { | |
| 96 | + audioBroadcastCatchList.add(data.get(key)); | |
| 97 | + } | |
| 98 | + } | |
| 99 | + } | |
| 100 | + | |
| 101 | + return audioBroadcastCatchList; | |
| 102 | + } | |
| 103 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java
| ... | ... | @@ -106,13 +106,13 @@ public class SipRunner implements CommandLineRunner { |
| 106 | 106 | if (sendRtpItems.size() > 0) { |
| 107 | 107 | for (SendRtpItem sendRtpItem : sendRtpItems) { |
| 108 | 108 | MediaServerItem mediaServerItem = mediaServerService.getOne(sendRtpItem.getMediaServerId()); |
| 109 | - redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(),sendRtpItem.getChannelId(), sendRtpItem.getCallId(),sendRtpItem.getStreamId()); | |
| 109 | + redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(),sendRtpItem.getChannelId(), sendRtpItem.getCallId(),sendRtpItem.getStream()); | |
| 110 | 110 | if (mediaServerItem != null) { |
| 111 | 111 | ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrc()); |
| 112 | 112 | Map<String, Object> param = new HashMap<>(); |
| 113 | 113 | param.put("vhost","__defaultVhost__"); |
| 114 | 114 | param.put("app",sendRtpItem.getApp()); |
| 115 | - param.put("stream",sendRtpItem.getStreamId()); | |
| 115 | + param.put("stream",sendRtpItem.getStream()); | |
| 116 | 116 | param.put("ssrc",sendRtpItem.getSsrc()); |
| 117 | 117 | JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(mediaServerItem, param); |
| 118 | 118 | if (jsonObject != null && jsonObject.getInteger("code") == 0) { | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
| ... | ... | @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd; |
| 2 | 2 | |
| 3 | 3 | import com.genersoft.iot.vmp.common.StreamInfo; |
| 4 | 4 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; |
| 5 | +import com.genersoft.iot.vmp.gb28181.bean.*; | |
| 5 | 6 | import com.genersoft.iot.vmp.gb28181.bean.Device; |
| 6 | 7 | import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; |
| 7 | 8 | import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; |
| ... | ... | @@ -124,13 +125,19 @@ public interface ISIPCommander { |
| 124 | 125 | String startTime, String endTime, int downloadSpeed, ZlmHttpHookSubscribe.Event hookEvent, |
| 125 | 126 | SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; |
| 126 | 127 | |
| 128 | + | |
| 127 | 129 | /** |
| 128 | 130 | * 视频流停止 |
| 129 | 131 | */ |
| 130 | 132 | void streamByeCmd(Device device, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException; |
| 131 | 133 | |
| 134 | + void talkStreamCmd(MediaServerItem mediaServerItem, SendRtpItem sendRtpItem, Device device, String channelId, String callId, ZlmHttpHookSubscribe.Event event, ZlmHttpHookSubscribe.Event eventForPush, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; | |
| 135 | + | |
| 136 | + | |
| 132 | 137 | void streamByeCmd(Device device, String channelId, String stream, String callId) throws InvalidArgumentException, ParseException, SipException, SsrcTransactionNotFoundException; |
| 133 | 138 | |
| 139 | + void streamByeCmd(Device device, String channelId, SipTransactionInfo sipTransactionInfo, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException; | |
| 140 | + | |
| 134 | 141 | /** |
| 135 | 142 | * 回放暂停 |
| 136 | 143 | */ |
| ... | ... | @@ -160,22 +167,16 @@ public interface ISIPCommander { |
| 160 | 167 | void playbackControlCmd(Device device, StreamInfo streamInfo, String content,SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException, InvalidArgumentException, ParseException; |
| 161 | 168 | |
| 162 | 169 | |
| 170 | + void streamByeCmdForDeviceInvite(Device device, String channelId, SipTransactionInfo sipTransactionInfo, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException; | |
| 171 | + | |
| 163 | 172 | /** |
| 173 | + * /** | |
| 164 | 174 | * 语音广播 |
| 165 | - * | |
| 166 | - * @param device 视频设备 | |
| 167 | - * @param channelId 预览通道 | |
| 168 | - */ | |
| 169 | - void audioBroadcastCmd(Device device,String channelId); | |
| 170 | - | |
| 171 | - /** | |
| 172 | - * 语音广播 | |
| 173 | - * | |
| 174 | - * @param device 视频设备 | |
| 175 | + * | |
| 176 | + * @param device 视频设备 | |
| 175 | 177 | */ |
| 176 | - void audioBroadcastCmd(Device device, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; | |
| 177 | - void audioBroadcastCmd(Device device) throws InvalidArgumentException, SipException, ParseException; | |
| 178 | - | |
| 178 | + void audioBroadcastCmd(Device device, String channelId, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; | |
| 179 | + | |
| 179 | 180 | /** |
| 180 | 181 | * 音视频录像控制 |
| 181 | 182 | * |
| ... | ... | @@ -362,4 +363,5 @@ public interface ISIPCommander { |
| 362 | 363 | */ |
| 363 | 364 | void sendAlarmMessage(Device device, DeviceAlarm deviceAlarm) throws InvalidArgumentException, SipException, ParseException; |
| 364 | 365 | |
| 366 | + | |
| 365 | 367 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java
| 1 | 1 | package com.genersoft.iot.vmp.gb28181.transmit.cmd; |
| 2 | 2 | |
| 3 | +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; | |
| 3 | 4 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 4 | 5 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| 6 | +import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; | |
| 7 | +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | |
| 5 | 8 | import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; |
| 9 | +import com.genersoft.iot.vmp.service.bean.SSRCInfo; | |
| 6 | 10 | |
| 7 | 11 | import javax.sip.InvalidArgumentException; |
| 8 | 12 | import javax.sip.SipException; |
| ... | ... | @@ -14,6 +18,7 @@ public interface ISIPCommanderForPlatform { |
| 14 | 18 | |
| 15 | 19 | /** |
| 16 | 20 | * 向上级平台注册 |
| 21 | + * | |
| 17 | 22 | * @param parentPlatform |
| 18 | 23 | * @return |
| 19 | 24 | */ |
| ... | ... | @@ -26,6 +31,7 @@ public interface ISIPCommanderForPlatform { |
| 26 | 31 | |
| 27 | 32 | /** |
| 28 | 33 | * 向上级平台注销 |
| 34 | + * | |
| 29 | 35 | * @param parentPlatform |
| 30 | 36 | * @return |
| 31 | 37 | */ |
| ... | ... | @@ -34,26 +40,33 @@ public interface ISIPCommanderForPlatform { |
| 34 | 40 | |
| 35 | 41 | /** |
| 36 | 42 | * 向上级平发送心跳信息 |
| 43 | + * | |
| 37 | 44 | * @param parentPlatform |
| 38 | 45 | * @return callId(作为接受回复的判定) |
| 39 | 46 | */ |
| 40 | - String keepalive(ParentPlatform parentPlatform,SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws SipException, InvalidArgumentException, ParseException; | |
| 47 | + String keepalive(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) | |
| 48 | + throws SipException, InvalidArgumentException, ParseException; | |
| 41 | 49 | |
| 42 | 50 | |
| 43 | 51 | /** |
| 44 | 52 | * 向上级回复通道信息 |
| 45 | - * @param channel 通道信息 | |
| 53 | + * | |
| 54 | + * @param channel 通道信息 | |
| 46 | 55 | * @param parentPlatform 平台信息 |
| 47 | 56 | * @param sn |
| 48 | 57 | * @param fromTag |
| 49 | 58 | * @param size |
| 50 | 59 | * @return |
| 51 | 60 | */ |
| 52 | - void catalogQuery(DeviceChannel channel, ParentPlatform parentPlatform, String sn, String fromTag, int size) throws SipException, InvalidArgumentException, ParseException; | |
| 53 | - void catalogQuery(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag) throws InvalidArgumentException, ParseException, SipException; | |
| 61 | + void catalogQuery(DeviceChannel channel, ParentPlatform parentPlatform, String sn, String fromTag, int size) | |
| 62 | + throws SipException, InvalidArgumentException, ParseException; | |
| 63 | + | |
| 64 | + void catalogQuery(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag) | |
| 65 | + throws InvalidArgumentException, ParseException, SipException; | |
| 54 | 66 | |
| 55 | 67 | /** |
| 56 | 68 | * 向上级回复DeviceInfo查询信息 |
| 69 | + * | |
| 57 | 70 | * @param parentPlatform 平台信息 |
| 58 | 71 | * @param sn SN |
| 59 | 72 | * @param fromTag FROM头的tag信息 |
| ... | ... | @@ -63,6 +76,7 @@ public interface ISIPCommanderForPlatform { |
| 63 | 76 | |
| 64 | 77 | /** |
| 65 | 78 | * 向上级回复DeviceStatus查询信息 |
| 79 | + * | |
| 66 | 80 | * @param parentPlatform 平台信息 |
| 67 | 81 | * @param sn |
| 68 | 82 | * @param fromTag |
| ... | ... | @@ -72,23 +86,27 @@ public interface ISIPCommanderForPlatform { |
| 72 | 86 | |
| 73 | 87 | /** |
| 74 | 88 | * 向上级回复移动位置订阅消息 |
| 89 | + * | |
| 75 | 90 | * @param parentPlatform 平台信息 |
| 76 | - * @param gpsMsgInfo GPS信息 | |
| 77 | - * @param subscribeInfo 订阅相关的信息 | |
| 91 | + * @param gpsMsgInfo GPS信息 | |
| 92 | + * @param subscribeInfo 订阅相关的信息 | |
| 78 | 93 | * @return |
| 79 | 94 | */ |
| 80 | - void sendNotifyMobilePosition(ParentPlatform parentPlatform, GPSMsgInfo gpsMsgInfo, SubscribeInfo subscribeInfo) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException; | |
| 95 | + void sendNotifyMobilePosition(ParentPlatform parentPlatform, GPSMsgInfo gpsMsgInfo, SubscribeInfo subscribeInfo) | |
| 96 | + throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException; | |
| 81 | 97 | |
| 82 | 98 | /** |
| 83 | 99 | * 向上级回复报警消息 |
| 100 | + * | |
| 84 | 101 | * @param parentPlatform 平台信息 |
| 85 | - * @param deviceAlarm 报警信息信息 | |
| 102 | + * @param deviceAlarm 报警信息信息 | |
| 86 | 103 | * @return |
| 87 | 104 | */ |
| 88 | 105 | void sendAlarmMessage(ParentPlatform parentPlatform, DeviceAlarm deviceAlarm) throws SipException, InvalidArgumentException, ParseException; |
| 89 | 106 | |
| 90 | 107 | /** |
| 91 | 108 | * 回复catalog事件-增加/更新 |
| 109 | + * | |
| 92 | 110 | * @param parentPlatform |
| 93 | 111 | * @param deviceChannels |
| 94 | 112 | */ |
| ... | ... | @@ -96,22 +114,28 @@ public interface ISIPCommanderForPlatform { |
| 96 | 114 | |
| 97 | 115 | /** |
| 98 | 116 | * 回复catalog事件-删除 |
| 117 | + * | |
| 99 | 118 | * @param parentPlatform |
| 100 | 119 | * @param deviceChannels |
| 101 | 120 | */ |
| 102 | - void sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException; | |
| 121 | + void sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, | |
| 122 | + SubscribeInfo subscribeInfo, Integer index) throws InvalidArgumentException, | |
| 123 | + ParseException, NoSuchFieldException, SipException, IllegalAccessException; | |
| 103 | 124 | |
| 104 | 125 | /** |
| 105 | 126 | * 回复recordInfo |
| 106 | - * @param deviceChannel 通道信息 | |
| 127 | + * | |
| 128 | + * @param deviceChannel 通道信息 | |
| 107 | 129 | * @param parentPlatform 平台信息 |
| 108 | - * @param fromTag fromTag | |
| 109 | - * @param recordInfo 录像信息 | |
| 130 | + * @param fromTag fromTag | |
| 131 | + * @param recordInfo 录像信息 | |
| 110 | 132 | */ |
| 111 | - void recordInfo(DeviceChannel deviceChannel, ParentPlatform parentPlatform, String fromTag, RecordInfo recordInfo) throws SipException, InvalidArgumentException, ParseException; | |
| 133 | + void recordInfo(DeviceChannel deviceChannel, ParentPlatform parentPlatform, String fromTag, RecordInfo recordInfo) | |
| 134 | + throws SipException, InvalidArgumentException, ParseException; | |
| 112 | 135 | |
| 113 | 136 | /** |
| 114 | 137 | * 录像播放推送完成时发送MediaStatus消息 |
| 138 | + * | |
| 115 | 139 | * @param platform |
| 116 | 140 | * @param sendRtpItem |
| 117 | 141 | * @return |
| ... | ... | @@ -120,9 +144,19 @@ public interface ISIPCommanderForPlatform { |
| 120 | 144 | |
| 121 | 145 | /** |
| 122 | 146 | * 向发起点播的上级回复bye |
| 147 | + * | |
| 123 | 148 | * @param platform 平台信息 |
| 124 | - * @param callId callId | |
| 149 | + * @param callId callId | |
| 125 | 150 | */ |
| 126 | 151 | void streamByeCmd(ParentPlatform platform, String callId) throws SipException, InvalidArgumentException, ParseException; |
| 152 | + | |
| 127 | 153 | void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem) throws SipException, InvalidArgumentException, ParseException; |
| 154 | + | |
| 155 | + void streamByeCmd(ParentPlatform platform, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException; | |
| 156 | + | |
| 157 | + void broadcastInviteCmd(ParentPlatform platform, String channelId, MediaServerItem mediaServerItem, | |
| 158 | + SSRCInfo ssrcInfo, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, | |
| 159 | + SipSubscribe.Event errorEvent) throws ParseException, SipException, InvalidArgumentException; | |
| 160 | + | |
| 161 | + void broadcastResultCmd(ParentPlatform platform, DeviceChannel deviceChannel, String sn, boolean result, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; | |
| 128 | 162 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java
| ... | ... | @@ -4,6 +4,7 @@ import com.genersoft.iot.vmp.conf.SipConfig; |
| 4 | 4 | import com.genersoft.iot.vmp.gb28181.SipLayer; |
| 5 | 5 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| 6 | 6 | import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; |
| 7 | +import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo; | |
| 7 | 8 | import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo; |
| 8 | 9 | import com.genersoft.iot.vmp.gb28181.utils.SipUtils; |
| 9 | 10 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| ... | ... | @@ -55,7 +56,7 @@ public class SIPRequestHeaderPlarformProvider { |
| 55 | 56 | //via |
| 56 | 57 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); |
| 57 | 58 | ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), |
| 58 | - Integer.parseInt(parentPlatform.getDevicePort()), parentPlatform.getTransport(), SipUtils.getNewViaTag()); | |
| 59 | + parentPlatform.getDevicePort(), parentPlatform.getTransport(), SipUtils.getNewViaTag()); | |
| 59 | 60 | viaHeader.setRPort(); |
| 60 | 61 | viaHeaders.add(viaHeader); |
| 61 | 62 | //from |
| ... | ... | @@ -182,7 +183,7 @@ public class SIPRequestHeaderPlarformProvider { |
| 182 | 183 | SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), serverAddress); |
| 183 | 184 | // via |
| 184 | 185 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); |
| 185 | - ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), Integer.parseInt(parentPlatform.getDevicePort()), | |
| 186 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), parentPlatform.getDevicePort(), | |
| 186 | 187 | parentPlatform.getTransport(), viaTag); |
| 187 | 188 | viaHeader.setRPort(); |
| 188 | 189 | viaHeaders.add(viaHeader); |
| ... | ... | @@ -219,7 +220,7 @@ public class SIPRequestHeaderPlarformProvider { |
| 219 | 220 | SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP()+ ":" + parentPlatform.getServerPort()); |
| 220 | 221 | // via |
| 221 | 222 | ArrayList<ViaHeader> viaHeaders = new ArrayList<>(); |
| 222 | - ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), Integer.parseInt(parentPlatform.getDevicePort()), | |
| 223 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), parentPlatform.getDevicePort(), | |
| 223 | 224 | parentPlatform.getTransport(), SipUtils.getNewViaTag()); |
| 224 | 225 | viaHeader.setRPort(); |
| 225 | 226 | viaHeaders.add(viaHeader); |
| ... | ... | @@ -279,7 +280,7 @@ public class SIPRequestHeaderPlarformProvider { |
| 279 | 280 | SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+ ":" + platform.getServerPort()); |
| 280 | 281 | // via |
| 281 | 282 | ArrayList<ViaHeader> viaHeaders = new ArrayList<>(); |
| 282 | - ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(platform.getDeviceIp(), Integer.parseInt(platform.getDevicePort()), | |
| 283 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(platform.getDeviceIp(), platform.getDevicePort(), | |
| 283 | 284 | platform.getTransport(), SipUtils.getNewViaTag()); |
| 284 | 285 | viaHeader.setRPort(); |
| 285 | 286 | viaHeaders.add(viaHeader); |
| ... | ... | @@ -313,4 +314,80 @@ public class SIPRequestHeaderPlarformProvider { |
| 313 | 314 | |
| 314 | 315 | return request; |
| 315 | 316 | } |
| 317 | + | |
| 318 | + public Request createInviteRequest(ParentPlatform platform, String channelId, String content, String viaTag, String fromTag, String ssrc, CallIdHeader callIdHeader) throws PeerUnavailableException, ParseException, InvalidArgumentException { | |
| 319 | + Request request = null; | |
| 320 | + //请求行 | |
| 321 | + String platformHostAddress = platform.getServerIP() + ":" + platform.getServerPort(); | |
| 322 | + String localHostAddress = sipLayer.getLocalIp(platform.getDeviceIp())+":"+ platform.getDevicePort(); | |
| 323 | + SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, platformHostAddress); | |
| 324 | + //via | |
| 325 | + ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | |
| 326 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(platform.getDeviceIp()), platform.getDevicePort(), platform.getTransport(), viaTag); | |
| 327 | + viaHeader.setRPort(); | |
| 328 | + viaHeaders.add(viaHeader); | |
| 329 | + | |
| 330 | + //from | |
| 331 | + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(platform.getDeviceGBId(), sipConfig.getDomain()); | |
| 332 | + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); | |
| 333 | + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack | |
| 334 | + //to | |
| 335 | + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, platformHostAddress); | |
| 336 | + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | |
| 337 | + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress,null); | |
| 338 | + | |
| 339 | + //Forwards | |
| 340 | + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); | |
| 341 | + | |
| 342 | + //ceq | |
| 343 | + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE); | |
| 344 | + request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); | |
| 345 | + | |
| 346 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | |
| 347 | + | |
| 348 | + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(),localHostAddress)); | |
| 349 | + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); | |
| 350 | + // Subject | |
| 351 | + SubjectHeader subjectHeader = SipFactory.getInstance().createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", channelId, ssrc, sipConfig.getId(), 0)); | |
| 352 | + request.addHeader(subjectHeader); | |
| 353 | + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP"); | |
| 354 | + request.setContent(content, contentTypeHeader); | |
| 355 | + return request; | |
| 356 | + } | |
| 357 | + | |
| 358 | + public Request createByteRequest(ParentPlatform platform, String channelId, SipTransactionInfo transactionInfo) throws PeerUnavailableException, ParseException, InvalidArgumentException { | |
| 359 | + String deviceHostAddress = platform.getDeviceIp() + ":" + platform.getDevicePort(); | |
| 360 | + Request request = null; | |
| 361 | + SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, deviceHostAddress); | |
| 362 | + | |
| 363 | + // via | |
| 364 | + ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | |
| 365 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(platform.getDeviceIp()), platform.getDevicePort(), platform.getTransport(), SipUtils.getNewViaTag()); | |
| 366 | + viaHeaders.add(viaHeader); | |
| 367 | + //from | |
| 368 | + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain()); | |
| 369 | + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); | |
| 370 | + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, transactionInfo.isAsSender()?transactionInfo.getFromTag():transactionInfo.getToTag()); | |
| 371 | + //to | |
| 372 | + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, deviceHostAddress); | |
| 373 | + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | |
| 374 | + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress,transactionInfo.isAsSender()?transactionInfo.getToTag():transactionInfo.getFromTag()); | |
| 375 | + | |
| 376 | + //Forwards | |
| 377 | + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); | |
| 378 | + | |
| 379 | + //ceq | |
| 380 | + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE); | |
| 381 | + CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(transactionInfo.getCallId()); | |
| 382 | + request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.BYE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); | |
| 383 | + | |
| 384 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | |
| 385 | + | |
| 386 | + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(platform.getDeviceIp())+":"+ platform.getDevicePort())); | |
| 387 | + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); | |
| 388 | + | |
| 389 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | |
| 390 | + | |
| 391 | + return request; | |
| 392 | + } | |
| 316 | 393 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
| 1 | -package com.genersoft.iot.vmp.gb28181.transmit.cmd; | |
| 2 | - | |
| 3 | -import com.genersoft.iot.vmp.conf.SipConfig; | |
| 4 | -import com.genersoft.iot.vmp.gb28181.SipLayer; | |
| 5 | -import com.genersoft.iot.vmp.gb28181.bean.Device; | |
| 6 | -import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo; | |
| 7 | -import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | |
| 8 | -import com.genersoft.iot.vmp.gb28181.utils.SipUtils; | |
| 9 | -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | |
| 10 | -import com.genersoft.iot.vmp.utils.GitUtil; | |
| 11 | -import gov.nist.javax.sip.message.SIPRequest; | |
| 12 | -import gov.nist.javax.sip.message.SIPResponse; | |
| 13 | -import org.springframework.beans.factory.annotation.Autowired; | |
| 14 | -import org.springframework.stereotype.Component; | |
| 15 | - | |
| 16 | -import javax.sip.InvalidArgumentException; | |
| 17 | -import javax.sip.PeerUnavailableException; | |
| 18 | -import javax.sip.SipException; | |
| 19 | -import javax.sip.SipFactory; | |
| 20 | -import javax.sip.address.Address; | |
| 21 | -import javax.sip.address.SipURI; | |
| 22 | -import javax.sip.header.*; | |
| 23 | -import javax.sip.message.Request; | |
| 24 | -import java.text.ParseException; | |
| 25 | -import java.util.ArrayList; | |
| 26 | - | |
| 27 | -/** | |
| 28 | - * @description:摄像头命令request创造器 TODO 冗余代码太多待优化 | |
| 29 | - * @author: swwheihei | |
| 30 | - * @date: 2020年5月6日 上午9:29:02 | |
| 31 | - */ | |
| 32 | -@Component | |
| 33 | -public class SIPRequestHeaderProvider { | |
| 34 | - | |
| 35 | - @Autowired | |
| 36 | - private SipConfig sipConfig; | |
| 37 | - | |
| 38 | - @Autowired | |
| 39 | - private SipLayer sipLayer; | |
| 40 | - | |
| 41 | - @Autowired | |
| 42 | - private GitUtil gitUtil; | |
| 43 | - | |
| 44 | - @Autowired | |
| 45 | - private IRedisCatchStorage redisCatchStorage; | |
| 46 | - | |
| 47 | - @Autowired | |
| 48 | - private VideoStreamSessionManager streamSession; | |
| 49 | - | |
| 50 | - public Request createMessageRequest(Device device, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { | |
| 51 | - Request request = null; | |
| 52 | - // sipuri | |
| 53 | - SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); | |
| 54 | - // via | |
| 55 | - ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | |
| 56 | - ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), viaTag); | |
| 57 | - viaHeader.setRPort(); | |
| 58 | - viaHeaders.add(viaHeader); | |
| 59 | - // from | |
| 60 | - SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain()); | |
| 61 | - Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); | |
| 62 | - FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag); | |
| 63 | - // to | |
| 64 | - SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); | |
| 65 | - Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | |
| 66 | - ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, toTag); | |
| 67 | - | |
| 68 | - // Forwards | |
| 69 | - MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); | |
| 70 | - // ceq | |
| 71 | - CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.MESSAGE); | |
| 72 | - | |
| 73 | - request = SipFactory.getInstance().createMessageFactory().createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader, | |
| 74 | - toHeader, viaHeaders, maxForwards); | |
| 75 | - | |
| 76 | - request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | |
| 77 | - | |
| 78 | - ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); | |
| 79 | - request.setContent(content, contentTypeHeader); | |
| 80 | - return request; | |
| 81 | - } | |
| 82 | - | |
| 83 | - public Request createInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, String ssrc, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { | |
| 84 | - Request request = null; | |
| 85 | - //请求行 | |
| 86 | - SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress()); | |
| 87 | - //via | |
| 88 | - ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | |
| 89 | - HeaderFactory headerFactory = SipFactory.getInstance().createHeaderFactory(); | |
| 90 | - ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), viaTag); | |
| 91 | - viaHeader.setRPort(); | |
| 92 | - viaHeaders.add(viaHeader); | |
| 93 | - | |
| 94 | - //from | |
| 95 | - SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain()); | |
| 96 | - Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); | |
| 97 | - FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack | |
| 98 | - //to | |
| 99 | - SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress()); | |
| 100 | - Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | |
| 101 | - ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress,null); | |
| 102 | - | |
| 103 | - //Forwards | |
| 104 | - MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); | |
| 105 | - | |
| 106 | - //ceq | |
| 107 | - CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE); | |
| 108 | - request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); | |
| 109 | - | |
| 110 | - request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | |
| 111 | - | |
| 112 | - Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort())); | |
| 113 | - // Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), device.getHost().getIp()+":"+device.getHost().getPort())); | |
| 114 | - request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); | |
| 115 | - // Subject | |
| 116 | - SubjectHeader subjectHeader = SipFactory.getInstance().createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", channelId, ssrc, sipConfig.getId(), 0)); | |
| 117 | - request.addHeader(subjectHeader); | |
| 118 | - ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP"); | |
| 119 | - request.setContent(content, contentTypeHeader); | |
| 120 | - return request; | |
| 121 | - } | |
| 122 | - | |
| 123 | - public Request createPlaybackInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader, String ssrc) throws ParseException, InvalidArgumentException, PeerUnavailableException { | |
| 124 | - Request request = null; | |
| 125 | - //请求行 | |
| 126 | - SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress()); | |
| 127 | - // via | |
| 128 | - ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | |
| 129 | - ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), viaTag); | |
| 130 | - viaHeader.setRPort(); | |
| 131 | - viaHeaders.add(viaHeader); | |
| 132 | - //from | |
| 133 | - SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain()); | |
| 134 | - Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); | |
| 135 | - FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack | |
| 136 | - //to | |
| 137 | - SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress()); | |
| 138 | - Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | |
| 139 | - ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress,null); | |
| 140 | - | |
| 141 | - //Forwards | |
| 142 | - MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); | |
| 143 | - | |
| 144 | - //ceq | |
| 145 | - CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE); | |
| 146 | - request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); | |
| 147 | - | |
| 148 | - Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort())); | |
| 149 | - // Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), device.getHost().getIp()+":"+device.getHost().getPort())); | |
| 150 | - request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); | |
| 151 | - | |
| 152 | - request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | |
| 153 | - | |
| 154 | - // Subject | |
| 155 | - SubjectHeader subjectHeader = SipFactory.getInstance().createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", channelId, ssrc, sipConfig.getId(), 0)); | |
| 156 | - request.addHeader(subjectHeader); | |
| 157 | - | |
| 158 | - ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP"); | |
| 159 | - request.setContent(content, contentTypeHeader); | |
| 160 | - return request; | |
| 161 | - } | |
| 162 | - | |
| 163 | - public Request createByteRequest(Device device, String channelId, SipTransactionInfo transactionInfo) throws ParseException, InvalidArgumentException, PeerUnavailableException { | |
| 164 | - Request request = null; | |
| 165 | - //请求行 | |
| 166 | - SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress()); | |
| 167 | -// SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); | |
| 168 | - // via | |
| 169 | - ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | |
| 170 | - ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), SipUtils.getNewViaTag()); | |
| 171 | - viaHeaders.add(viaHeader); | |
| 172 | - //from | |
| 173 | - SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain()); | |
| 174 | - Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); | |
| 175 | - FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, transactionInfo.getFromTag()); | |
| 176 | - //to | |
| 177 | - SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId,device.getHostAddress()); | |
| 178 | -// SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(),device.getHostAddress()); | |
| 179 | - Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | |
| 180 | - ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, transactionInfo.getToTag()); | |
| 181 | - | |
| 182 | - //Forwards | |
| 183 | - MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); | |
| 184 | - | |
| 185 | - //ceq | |
| 186 | - CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE); | |
| 187 | - CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(transactionInfo.getCallId()); | |
| 188 | - request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.BYE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); | |
| 189 | - | |
| 190 | - request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | |
| 191 | - | |
| 192 | - Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort())); | |
| 193 | - request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); | |
| 194 | - | |
| 195 | - request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | |
| 196 | - | |
| 197 | - return request; | |
| 198 | - } | |
| 199 | - | |
| 200 | - public Request createSubscribeRequest(Device device, String content, SIPRequest requestOld, Integer expires, String event, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { | |
| 201 | - Request request = null; | |
| 202 | - // sipuri | |
| 203 | - SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); | |
| 204 | - // via | |
| 205 | - ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | |
| 206 | - ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), | |
| 207 | - device.getTransport(), SipUtils.getNewViaTag()); | |
| 208 | - viaHeader.setRPort(); | |
| 209 | - viaHeaders.add(viaHeader); | |
| 210 | - // from | |
| 211 | - SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain()); | |
| 212 | - Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); | |
| 213 | - FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, requestOld == null ? SipUtils.getNewFromTag() :requestOld.getFromTag()); | |
| 214 | - // to | |
| 215 | - SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); | |
| 216 | - Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | |
| 217 | - ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, requestOld == null ? null :requestOld.getToTag()); | |
| 218 | - | |
| 219 | - // Forwards | |
| 220 | - MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); | |
| 221 | - | |
| 222 | - // ceq | |
| 223 | - CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.SUBSCRIBE); | |
| 224 | - | |
| 225 | - request = SipFactory.getInstance().createMessageFactory().createRequest(requestURI, Request.SUBSCRIBE, callIdHeader, cSeqHeader, fromHeader, | |
| 226 | - toHeader, viaHeaders, maxForwards); | |
| 227 | - | |
| 228 | - | |
| 229 | - Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort())); | |
| 230 | - request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); | |
| 231 | - | |
| 232 | - // Expires | |
| 233 | - ExpiresHeader expireHeader = SipFactory.getInstance().createHeaderFactory().createExpiresHeader(expires); | |
| 234 | - request.addHeader(expireHeader); | |
| 235 | - | |
| 236 | - // Event | |
| 237 | - EventHeader eventHeader = SipFactory.getInstance().createHeaderFactory().createEventHeader(event); | |
| 238 | - | |
| 239 | - int random = (int) Math.floor(Math.random() * 10000); | |
| 240 | - eventHeader.setEventId(random + ""); | |
| 241 | - request.addHeader(eventHeader); | |
| 242 | - | |
| 243 | - ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); | |
| 244 | - request.setContent(content, contentTypeHeader); | |
| 245 | - | |
| 246 | - request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | |
| 247 | - | |
| 248 | - return request; | |
| 249 | - } | |
| 250 | - | |
| 251 | - public SIPRequest createInfoRequest(Device device, String channelId, String content, SipTransactionInfo transactionInfo) | |
| 252 | - throws SipException, ParseException, InvalidArgumentException { | |
| 253 | - if (device == null || transactionInfo == null) { | |
| 254 | - return null; | |
| 255 | - } | |
| 256 | - SIPRequest request = null; | |
| 257 | - //请求行 | |
| 258 | - SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress()); | |
| 259 | - // via | |
| 260 | - ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | |
| 261 | - ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), SipUtils.getNewViaTag()); | |
| 262 | - viaHeaders.add(viaHeader); | |
| 263 | - //from | |
| 264 | - SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain()); | |
| 265 | - Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); | |
| 266 | - FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, transactionInfo.getFromTag()); | |
| 267 | - //to | |
| 268 | - SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId,device.getHostAddress()); | |
| 269 | - Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | |
| 270 | - ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, transactionInfo.getToTag()); | |
| 271 | - | |
| 272 | - //Forwards | |
| 273 | - MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); | |
| 274 | - | |
| 275 | - //ceq | |
| 276 | - CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INFO); | |
| 277 | - CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(transactionInfo.getCallId()); | |
| 278 | - request = (SIPRequest)SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.INFO, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); | |
| 279 | - | |
| 280 | - request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | |
| 281 | - | |
| 282 | - Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort())); | |
| 283 | - request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); | |
| 284 | - | |
| 285 | - request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | |
| 286 | - | |
| 287 | - if (content != null) { | |
| 288 | - ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application", | |
| 289 | - "MANSRTSP"); | |
| 290 | - request.setContent(content, contentTypeHeader); | |
| 291 | - } | |
| 292 | - return request; | |
| 293 | - } | |
| 294 | - | |
| 295 | - public Request createAckRequest(String localIp, SipURI sipURI, SIPResponse sipResponse) throws ParseException, InvalidArgumentException, PeerUnavailableException { | |
| 296 | - | |
| 297 | - | |
| 298 | - // via | |
| 299 | - ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | |
| 300 | - ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(localIp, sipConfig.getPort(), sipResponse.getTopmostViaHeader().getTransport(), SipUtils.getNewViaTag()); | |
| 301 | - viaHeaders.add(viaHeader); | |
| 302 | - | |
| 303 | - //Forwards | |
| 304 | - MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); | |
| 305 | - | |
| 306 | - //ceq | |
| 307 | - CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(sipResponse.getCSeqHeader().getSeqNumber(), Request.ACK); | |
| 308 | - | |
| 309 | - Request request = SipFactory.getInstance().createMessageFactory().createRequest(sipURI, Request.ACK, sipResponse.getCallIdHeader(), cSeqHeader, sipResponse.getFromHeader(), sipResponse.getToHeader(), viaHeaders, maxForwards); | |
| 310 | - | |
| 311 | - request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | |
| 312 | - | |
| 313 | - Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), localIp + ":"+sipConfig.getPort())); | |
| 314 | - request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); | |
| 315 | - | |
| 316 | - request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | |
| 317 | - | |
| 318 | - return request; | |
| 319 | - } | |
| 320 | -} | |
| 1 | +package com.genersoft.iot.vmp.gb28181.transmit.cmd; | |
| 2 | + | |
| 3 | +import com.genersoft.iot.vmp.conf.SipConfig; | |
| 4 | +import com.genersoft.iot.vmp.gb28181.SipLayer; | |
| 5 | +import com.genersoft.iot.vmp.gb28181.bean.Device; | |
| 6 | +import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo; | |
| 7 | +import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | |
| 8 | +import com.genersoft.iot.vmp.gb28181.utils.SipUtils; | |
| 9 | +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | |
| 10 | +import com.genersoft.iot.vmp.utils.GitUtil; | |
| 11 | +import gov.nist.javax.sip.message.SIPRequest; | |
| 12 | +import gov.nist.javax.sip.message.SIPResponse; | |
| 13 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 14 | +import org.springframework.stereotype.Component; | |
| 15 | + | |
| 16 | +import javax.sip.InvalidArgumentException; | |
| 17 | +import javax.sip.PeerUnavailableException; | |
| 18 | +import javax.sip.SipException; | |
| 19 | +import javax.sip.SipFactory; | |
| 20 | +import javax.sip.address.Address; | |
| 21 | +import javax.sip.address.SipURI; | |
| 22 | +import javax.sip.header.*; | |
| 23 | +import javax.sip.message.Request; | |
| 24 | +import java.text.ParseException; | |
| 25 | +import java.util.ArrayList; | |
| 26 | + | |
| 27 | +/** | |
| 28 | + * @description:摄像头命令request创造器 TODO 冗余代码太多待优化 | |
| 29 | + * @author: swwheihei | |
| 30 | + * @date: 2020年5月6日 上午9:29:02 | |
| 31 | + */ | |
| 32 | +@Component | |
| 33 | +public class SIPRequestHeaderProvider { | |
| 34 | + | |
| 35 | + @Autowired | |
| 36 | + private SipConfig sipConfig; | |
| 37 | + | |
| 38 | + @Autowired | |
| 39 | + private SipLayer sipLayer; | |
| 40 | + | |
| 41 | + @Autowired | |
| 42 | + private GitUtil gitUtil; | |
| 43 | + | |
| 44 | + @Autowired | |
| 45 | + private IRedisCatchStorage redisCatchStorage; | |
| 46 | + | |
| 47 | + @Autowired | |
| 48 | + private VideoStreamSessionManager streamSession; | |
| 49 | + | |
| 50 | + public Request createMessageRequest(Device device, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { | |
| 51 | + Request request = null; | |
| 52 | + // sipuri | |
| 53 | + SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); | |
| 54 | + // via | |
| 55 | + ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | |
| 56 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), viaTag); | |
| 57 | + viaHeader.setRPort(); | |
| 58 | + viaHeaders.add(viaHeader); | |
| 59 | + // from | |
| 60 | + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain()); | |
| 61 | + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); | |
| 62 | + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag); | |
| 63 | + // to | |
| 64 | + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); | |
| 65 | + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | |
| 66 | + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, toTag); | |
| 67 | + | |
| 68 | + // Forwards | |
| 69 | + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); | |
| 70 | + // ceq | |
| 71 | + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.MESSAGE); | |
| 72 | + | |
| 73 | + request = SipFactory.getInstance().createMessageFactory().createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader, | |
| 74 | + toHeader, viaHeaders, maxForwards); | |
| 75 | + | |
| 76 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | |
| 77 | + | |
| 78 | + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); | |
| 79 | + request.setContent(content, contentTypeHeader); | |
| 80 | + return request; | |
| 81 | + } | |
| 82 | + | |
| 83 | + public Request createInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, String ssrc, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { | |
| 84 | + Request request = null; | |
| 85 | + //请求行 | |
| 86 | + SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress()); | |
| 87 | + //via | |
| 88 | + ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | |
| 89 | + HeaderFactory headerFactory = SipFactory.getInstance().createHeaderFactory(); | |
| 90 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), viaTag); | |
| 91 | + viaHeader.setRPort(); | |
| 92 | + viaHeaders.add(viaHeader); | |
| 93 | + | |
| 94 | + //from | |
| 95 | + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain()); | |
| 96 | + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); | |
| 97 | + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack | |
| 98 | + //to | |
| 99 | + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress()); | |
| 100 | + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | |
| 101 | + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress,null); | |
| 102 | + | |
| 103 | + //Forwards | |
| 104 | + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); | |
| 105 | + | |
| 106 | + //ceq | |
| 107 | + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE); | |
| 108 | + request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); | |
| 109 | + | |
| 110 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | |
| 111 | + | |
| 112 | + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort())); | |
| 113 | + // Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), device.getHost().getIp()+":"+device.getHost().getPort())); | |
| 114 | + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); | |
| 115 | + // Subject | |
| 116 | + SubjectHeader subjectHeader = SipFactory.getInstance().createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", channelId, ssrc, sipConfig.getId(), 0)); | |
| 117 | + request.addHeader(subjectHeader); | |
| 118 | + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP"); | |
| 119 | + request.setContent(content, contentTypeHeader); | |
| 120 | + return request; | |
| 121 | + } | |
| 122 | + | |
| 123 | + public Request createPlaybackInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader, String ssrc) throws ParseException, InvalidArgumentException, PeerUnavailableException { | |
| 124 | + Request request = null; | |
| 125 | + //请求行 | |
| 126 | + SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress()); | |
| 127 | + // via | |
| 128 | + ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | |
| 129 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), viaTag); | |
| 130 | + viaHeader.setRPort(); | |
| 131 | + viaHeaders.add(viaHeader); | |
| 132 | + //from | |
| 133 | + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain()); | |
| 134 | + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); | |
| 135 | + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack | |
| 136 | + //to | |
| 137 | + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress()); | |
| 138 | + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | |
| 139 | + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress,null); | |
| 140 | + | |
| 141 | + //Forwards | |
| 142 | + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); | |
| 143 | + | |
| 144 | + //ceq | |
| 145 | + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE); | |
| 146 | + request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); | |
| 147 | + | |
| 148 | + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort())); | |
| 149 | + // Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), device.getHost().getIp()+":"+device.getHost().getPort())); | |
| 150 | + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); | |
| 151 | + | |
| 152 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | |
| 153 | + | |
| 154 | + // Subject | |
| 155 | + SubjectHeader subjectHeader = SipFactory.getInstance().createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", channelId, ssrc, sipConfig.getId(), 0)); | |
| 156 | + request.addHeader(subjectHeader); | |
| 157 | + | |
| 158 | + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP"); | |
| 159 | + request.setContent(content, contentTypeHeader); | |
| 160 | + return request; | |
| 161 | + } | |
| 162 | + | |
| 163 | + public Request createByteRequest(Device device, String channelId, SipTransactionInfo transactionInfo) throws ParseException, InvalidArgumentException, PeerUnavailableException { | |
| 164 | + Request request = null; | |
| 165 | + //请求行 | |
| 166 | + SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress()); | |
| 167 | +// SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); | |
| 168 | + // via | |
| 169 | + ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | |
| 170 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), SipUtils.getNewViaTag()); | |
| 171 | + viaHeaders.add(viaHeader); | |
| 172 | + //from | |
| 173 | + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain()); | |
| 174 | + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); | |
| 175 | + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, transactionInfo.getFromTag()); | |
| 176 | + //to | |
| 177 | + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId,device.getHostAddress()); | |
| 178 | +// SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(),device.getHostAddress()); | |
| 179 | + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | |
| 180 | + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, transactionInfo.getToTag()); | |
| 181 | + | |
| 182 | + //Forwards | |
| 183 | + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); | |
| 184 | + | |
| 185 | + //ceq | |
| 186 | + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE); | |
| 187 | + CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(transactionInfo.getCallId()); | |
| 188 | + request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.BYE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); | |
| 189 | + | |
| 190 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | |
| 191 | + | |
| 192 | + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort())); | |
| 193 | + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); | |
| 194 | + | |
| 195 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | |
| 196 | + | |
| 197 | + return request; | |
| 198 | + } | |
| 199 | + | |
| 200 | + public Request createByteRequestForDeviceInvite(Device device, String channelId, SipTransactionInfo transactionInfo) throws ParseException, InvalidArgumentException, PeerUnavailableException { | |
| 201 | + Request request = null; | |
| 202 | + //请求行 | |
| 203 | + SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress()); | |
| 204 | + // via | |
| 205 | + ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | |
| 206 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), SipUtils.getNewViaTag()); | |
| 207 | + viaHeaders.add(viaHeader); | |
| 208 | + //from | |
| 209 | + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain()); | |
| 210 | + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); | |
| 211 | + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, transactionInfo.getToTag()); | |
| 212 | + //to | |
| 213 | + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId,device.getHostAddress()); | |
| 214 | + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | |
| 215 | + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, transactionInfo.getFromTag()); | |
| 216 | + | |
| 217 | + //Forwards | |
| 218 | + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); | |
| 219 | + | |
| 220 | + //ceq | |
| 221 | + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE); | |
| 222 | + CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(transactionInfo.getCallId()); | |
| 223 | + request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.BYE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); | |
| 224 | + | |
| 225 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | |
| 226 | + | |
| 227 | + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort())); | |
| 228 | + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); | |
| 229 | + | |
| 230 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | |
| 231 | + | |
| 232 | + return request; | |
| 233 | + } | |
| 234 | + | |
| 235 | + public Request createSubscribeRequest(Device device, String content, SIPRequest requestOld, Integer expires, String event, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { | |
| 236 | + Request request = null; | |
| 237 | + // sipuri | |
| 238 | + SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); | |
| 239 | + // via | |
| 240 | + ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | |
| 241 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), | |
| 242 | + device.getTransport(), SipUtils.getNewViaTag()); | |
| 243 | + viaHeader.setRPort(); | |
| 244 | + viaHeaders.add(viaHeader); | |
| 245 | + // from | |
| 246 | + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain()); | |
| 247 | + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); | |
| 248 | + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, requestOld == null ? SipUtils.getNewFromTag() :requestOld.getFromTag()); | |
| 249 | + // to | |
| 250 | + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); | |
| 251 | + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | |
| 252 | + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, requestOld == null ? null :requestOld.getToTag()); | |
| 253 | + | |
| 254 | + // Forwards | |
| 255 | + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); | |
| 256 | + | |
| 257 | + // ceq | |
| 258 | + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.SUBSCRIBE); | |
| 259 | + | |
| 260 | + request = SipFactory.getInstance().createMessageFactory().createRequest(requestURI, Request.SUBSCRIBE, callIdHeader, cSeqHeader, fromHeader, | |
| 261 | + toHeader, viaHeaders, maxForwards); | |
| 262 | + | |
| 263 | + | |
| 264 | + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort())); | |
| 265 | + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); | |
| 266 | + | |
| 267 | + // Expires | |
| 268 | + ExpiresHeader expireHeader = SipFactory.getInstance().createHeaderFactory().createExpiresHeader(expires); | |
| 269 | + request.addHeader(expireHeader); | |
| 270 | + | |
| 271 | + // Event | |
| 272 | + EventHeader eventHeader = SipFactory.getInstance().createHeaderFactory().createEventHeader(event); | |
| 273 | + | |
| 274 | + int random = (int) Math.floor(Math.random() * 10000); | |
| 275 | + eventHeader.setEventId(random + ""); | |
| 276 | + request.addHeader(eventHeader); | |
| 277 | + | |
| 278 | + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); | |
| 279 | + request.setContent(content, contentTypeHeader); | |
| 280 | + | |
| 281 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | |
| 282 | + | |
| 283 | + return request; | |
| 284 | + } | |
| 285 | + | |
| 286 | + public SIPRequest createInfoRequest(Device device, String channelId, String content, SipTransactionInfo transactionInfo) | |
| 287 | + throws SipException, ParseException, InvalidArgumentException { | |
| 288 | + if (device == null || transactionInfo == null) { | |
| 289 | + return null; | |
| 290 | + } | |
| 291 | + SIPRequest request = null; | |
| 292 | + //请求行 | |
| 293 | + SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress()); | |
| 294 | + // via | |
| 295 | + ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | |
| 296 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), SipUtils.getNewViaTag()); | |
| 297 | + viaHeaders.add(viaHeader); | |
| 298 | + //from | |
| 299 | + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain()); | |
| 300 | + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); | |
| 301 | + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, transactionInfo.getFromTag()); | |
| 302 | + //to | |
| 303 | + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId,device.getHostAddress()); | |
| 304 | + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | |
| 305 | + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, transactionInfo.getToTag()); | |
| 306 | + | |
| 307 | + //Forwards | |
| 308 | + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); | |
| 309 | + | |
| 310 | + //ceq | |
| 311 | + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INFO); | |
| 312 | + CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(transactionInfo.getCallId()); | |
| 313 | + request = (SIPRequest)SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.INFO, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); | |
| 314 | + | |
| 315 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | |
| 316 | + | |
| 317 | + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort())); | |
| 318 | + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); | |
| 319 | + | |
| 320 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | |
| 321 | + | |
| 322 | + if (content != null) { | |
| 323 | + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application", | |
| 324 | + "MANSRTSP"); | |
| 325 | + request.setContent(content, contentTypeHeader); | |
| 326 | + } | |
| 327 | + return request; | |
| 328 | + } | |
| 329 | + | |
| 330 | + public Request createAckRequest(String localIp, SipURI sipURI, SIPResponse sipResponse) throws ParseException, InvalidArgumentException, PeerUnavailableException { | |
| 331 | + | |
| 332 | + | |
| 333 | + // via | |
| 334 | + ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | |
| 335 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(localIp, sipConfig.getPort(), sipResponse.getTopmostViaHeader().getTransport(), SipUtils.getNewViaTag()); | |
| 336 | + viaHeaders.add(viaHeader); | |
| 337 | + | |
| 338 | + //Forwards | |
| 339 | + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); | |
| 340 | + | |
| 341 | + //ceq | |
| 342 | + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(sipResponse.getCSeqHeader().getSeqNumber(), Request.ACK); | |
| 343 | + | |
| 344 | + Request request = SipFactory.getInstance().createMessageFactory().createRequest(sipURI, Request.ACK, sipResponse.getCallIdHeader(), cSeqHeader, sipResponse.getFromHeader(), sipResponse.getToHeader(), viaHeaders, maxForwards); | |
| 345 | + | |
| 346 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | |
| 347 | + | |
| 348 | + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), localIp + ":"+sipConfig.getPort())); | |
| 349 | + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); | |
| 350 | + | |
| 351 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | |
| 352 | + | |
| 353 | + return request; | |
| 354 | + } | |
| 355 | + public Request createBroadcastMessageRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { | |
| 356 | + Request request = null; | |
| 357 | + // sipuri | |
| 358 | + SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress()); | |
| 359 | + // via | |
| 360 | + ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | |
| 361 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipConfig.getIp(), sipConfig.getPort(), device.getTransport(), viaTag); | |
| 362 | + viaHeader.setRPort(); | |
| 363 | + viaHeaders.add(viaHeader); | |
| 364 | + // from | |
| 365 | + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain()); | |
| 366 | + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); | |
| 367 | + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag); | |
| 368 | + // to | |
| 369 | + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress()); | |
| 370 | + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | |
| 371 | + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, toTag); | |
| 372 | + | |
| 373 | + // Forwards | |
| 374 | + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); | |
| 375 | + // ceq | |
| 376 | + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.MESSAGE); | |
| 377 | + | |
| 378 | + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); | |
| 379 | + | |
| 380 | + request = SipFactory.getInstance().createMessageFactory().createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader, | |
| 381 | + toHeader, viaHeaders, maxForwards, contentTypeHeader, content); | |
| 382 | + | |
| 383 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | |
| 384 | + | |
| 385 | + return request; | |
| 386 | + } | |
| 387 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
| 1 | -package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl; | |
| 2 | - | |
| 3 | -import com.genersoft.iot.vmp.common.InviteSessionType; | |
| 4 | -import com.genersoft.iot.vmp.common.StreamInfo; | |
| 5 | -import com.genersoft.iot.vmp.conf.SipConfig; | |
| 6 | -import com.genersoft.iot.vmp.conf.UserSetting; | |
| 7 | -import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; | |
| 8 | -import com.genersoft.iot.vmp.gb28181.SipLayer; | |
| 9 | -import com.genersoft.iot.vmp.gb28181.bean.Device; | |
| 10 | -import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; | |
| 11 | -import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; | |
| 12 | -import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction; | |
| 13 | -import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | |
| 14 | -import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | |
| 15 | -import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; | |
| 16 | -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; | |
| 17 | -import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider; | |
| 18 | -import com.genersoft.iot.vmp.gb28181.utils.NumericUtil; | |
| 19 | -import com.genersoft.iot.vmp.gb28181.utils.SipUtils; | |
| 20 | -import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; | |
| 21 | -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; | |
| 22 | -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; | |
| 23 | -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | |
| 24 | -import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam; | |
| 25 | -import com.genersoft.iot.vmp.service.IMediaServerService; | |
| 26 | -import com.genersoft.iot.vmp.service.bean.SSRCInfo; | |
| 27 | -import com.genersoft.iot.vmp.utils.DateUtil; | |
| 28 | -import gov.nist.javax.sip.message.SIPRequest; | |
| 29 | -import gov.nist.javax.sip.message.SIPResponse; | |
| 30 | -import org.slf4j.Logger; | |
| 31 | -import org.slf4j.LoggerFactory; | |
| 32 | -import org.springframework.beans.factory.annotation.Autowired; | |
| 33 | -import org.springframework.context.annotation.DependsOn; | |
| 34 | -import org.springframework.stereotype.Component; | |
| 35 | -import org.springframework.util.ObjectUtils; | |
| 36 | - | |
| 37 | -import javax.sip.InvalidArgumentException; | |
| 38 | -import javax.sip.ResponseEvent; | |
| 39 | -import javax.sip.SipException; | |
| 40 | -import javax.sip.SipFactory; | |
| 41 | -import javax.sip.header.CallIdHeader; | |
| 42 | -import javax.sip.message.Request; | |
| 43 | -import java.text.ParseException; | |
| 44 | -import java.util.List; | |
| 45 | - | |
| 46 | -/** | |
| 47 | - * @description:设备能力接口,用于定义设备的控制、查询能力 | |
| 48 | - * @author: swwheihei | |
| 49 | - * @date: 2020年5月3日 下午9:22:48 | |
| 50 | - */ | |
| 51 | -@Component | |
| 52 | -@DependsOn("sipLayer") | |
| 53 | -public class SIPCommander implements ISIPCommander { | |
| 54 | - | |
| 55 | - private final Logger logger = LoggerFactory.getLogger(SIPCommander.class); | |
| 56 | - | |
| 57 | - @Autowired | |
| 58 | - private SipConfig sipConfig; | |
| 59 | - | |
| 60 | - @Autowired | |
| 61 | - private SipLayer sipLayer; | |
| 62 | - | |
| 63 | - @Autowired | |
| 64 | - private SIPSender sipSender; | |
| 65 | - | |
| 66 | - @Autowired | |
| 67 | - private SIPRequestHeaderProvider headerProvider; | |
| 68 | - | |
| 69 | - @Autowired | |
| 70 | - private VideoStreamSessionManager streamSession; | |
| 71 | - | |
| 72 | - @Autowired | |
| 73 | - private UserSetting userSetting; | |
| 74 | - | |
| 75 | - @Autowired | |
| 76 | - private ZlmHttpHookSubscribe subscribe; | |
| 77 | - | |
| 78 | - | |
| 79 | - | |
| 80 | - @Autowired | |
| 81 | - private IMediaServerService mediaServerService; | |
| 82 | - | |
| 83 | - | |
| 84 | - /** | |
| 85 | - * 云台方向放控制,使用配置文件中的默认镜头移动速度 | |
| 86 | - * | |
| 87 | - * @param device 控制设备 | |
| 88 | - * @param channelId 预览通道 | |
| 89 | - * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 | |
| 90 | - * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 | |
| 91 | - */ | |
| 92 | - @Override | |
| 93 | - public void ptzdirectCmd(Device device, String channelId, int leftRight, int upDown) throws InvalidArgumentException, ParseException, SipException { | |
| 94 | - ptzCmd(device, channelId, leftRight, upDown, 0, sipConfig.getPtzSpeed(), 0); | |
| 95 | - } | |
| 96 | - | |
| 97 | - /** | |
| 98 | - * 云台方向放控制 | |
| 99 | - * | |
| 100 | - * @param device 控制设备 | |
| 101 | - * @param channelId 预览通道 | |
| 102 | - * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 | |
| 103 | - * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 | |
| 104 | - * @param moveSpeed 镜头移动速度 | |
| 105 | - */ | |
| 106 | - @Override | |
| 107 | - public void ptzdirectCmd(Device device, String channelId, int leftRight, int upDown, int moveSpeed) throws InvalidArgumentException, ParseException, SipException { | |
| 108 | - ptzCmd(device, channelId, leftRight, upDown, 0, moveSpeed, 0); | |
| 109 | - } | |
| 110 | - | |
| 111 | - /** | |
| 112 | - * 云台缩放控制,使用配置文件中的默认镜头缩放速度 | |
| 113 | - * | |
| 114 | - * @param device 控制设备 | |
| 115 | - * @param channelId 预览通道 | |
| 116 | - * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 | |
| 117 | - */ | |
| 118 | - @Override | |
| 119 | - public void ptzZoomCmd(Device device, String channelId, int inOut) throws InvalidArgumentException, ParseException, SipException { | |
| 120 | - ptzCmd(device, channelId, 0, 0, inOut, 0, sipConfig.getPtzSpeed()); | |
| 121 | - } | |
| 122 | - | |
| 123 | - /** | |
| 124 | - * 云台缩放控制 | |
| 125 | - * | |
| 126 | - * @param device 控制设备 | |
| 127 | - * @param channelId 预览通道 | |
| 128 | - * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 | |
| 129 | - * @param zoomSpeed 镜头缩放速度 | |
| 130 | - */ | |
| 131 | - @Override | |
| 132 | - public void ptzZoomCmd(Device device, String channelId, int inOut, int zoomSpeed) throws InvalidArgumentException, ParseException, SipException { | |
| 133 | - ptzCmd(device, channelId, 0, 0, inOut, 0, zoomSpeed); | |
| 134 | - } | |
| 135 | - | |
| 136 | - /** | |
| 137 | - * 云台指令码计算 | |
| 138 | - * | |
| 139 | - * @param cmdCode 指令码 | |
| 140 | - * @param parameter1 数据1 | |
| 141 | - * @param parameter2 数据2 | |
| 142 | - * @param combineCode2 组合码2 | |
| 143 | - */ | |
| 144 | - public static String frontEndCmdString(int cmdCode, int parameter1, int parameter2, int combineCode2) { | |
| 145 | - StringBuilder builder = new StringBuilder("A50F01"); | |
| 146 | - String strTmp; | |
| 147 | - strTmp = String.format("%02X", cmdCode); | |
| 148 | - builder.append(strTmp, 0, 2); | |
| 149 | - strTmp = String.format("%02X", parameter1); | |
| 150 | - builder.append(strTmp, 0, 2); | |
| 151 | - strTmp = String.format("%02X", parameter2); | |
| 152 | - builder.append(strTmp, 0, 2); | |
| 153 | - //优化zoom变倍速率 | |
| 154 | - if ((combineCode2 > 0) && (combineCode2 <16)) | |
| 155 | - { | |
| 156 | - combineCode2 = 16; | |
| 157 | - } | |
| 158 | - strTmp = String.format("%X", combineCode2); | |
| 159 | - builder.append(strTmp, 0, 1).append("0"); | |
| 160 | - //计算校验码 | |
| 161 | - int checkCode = (0XA5 + 0X0F + 0X01 + cmdCode + parameter1 + parameter2 + (combineCode2 & 0XF0)) % 0X100; | |
| 162 | - strTmp = String.format("%02X", checkCode); | |
| 163 | - builder.append(strTmp, 0, 2); | |
| 164 | - return builder.toString(); | |
| 165 | - } | |
| 166 | - | |
| 167 | - /** | |
| 168 | - * 云台控制,支持方向与缩放控制 | |
| 169 | - * | |
| 170 | - * @param device 控制设备 | |
| 171 | - * @param channelId 预览通道 | |
| 172 | - * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 | |
| 173 | - * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 | |
| 174 | - * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 | |
| 175 | - * @param moveSpeed 镜头移动速度 | |
| 176 | - * @param zoomSpeed 镜头缩放速度 | |
| 177 | - */ | |
| 178 | - @Override | |
| 179 | - public void ptzCmd(Device device, String channelId, int leftRight, int upDown, int inOut, int moveSpeed, | |
| 180 | - int zoomSpeed) throws InvalidArgumentException, SipException, ParseException { | |
| 181 | - String cmdStr = SipUtils.cmdString(leftRight, upDown, inOut, moveSpeed, zoomSpeed); | |
| 182 | - StringBuilder ptzXml = new StringBuilder(200); | |
| 183 | - String charset = device.getCharset(); | |
| 184 | - ptzXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 185 | - ptzXml.append("<Control>\r\n"); | |
| 186 | - ptzXml.append("<CmdType>DeviceControl</CmdType>\r\n"); | |
| 187 | - ptzXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 188 | - ptzXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 189 | - ptzXml.append("<PTZCmd>" + cmdStr + "</PTZCmd>\r\n"); | |
| 190 | - ptzXml.append("<Info>\r\n"); | |
| 191 | - ptzXml.append("<ControlPriority>5</ControlPriority>\r\n"); | |
| 192 | - ptzXml.append("</Info>\r\n"); | |
| 193 | - ptzXml.append("</Control>\r\n"); | |
| 194 | - | |
| 195 | - Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 196 | - | |
| 197 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()),request); | |
| 198 | - } | |
| 199 | - | |
| 200 | - /** | |
| 201 | - * 前端控制,包括PTZ指令、FI指令、预置位指令、巡航指令、扫描指令和辅助开关指令 | |
| 202 | - * | |
| 203 | - * @param device 控制设备 | |
| 204 | - * @param channelId 预览通道 | |
| 205 | - * @param cmdCode 指令码 | |
| 206 | - * @param parameter1 数据1 | |
| 207 | - * @param parameter2 数据2 | |
| 208 | - * @param combineCode2 组合码2 | |
| 209 | - */ | |
| 210 | - @Override | |
| 211 | - public void frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2) throws SipException, InvalidArgumentException, ParseException { | |
| 212 | - | |
| 213 | - String cmdStr = frontEndCmdString(cmdCode, parameter1, parameter2, combineCode2); | |
| 214 | - StringBuffer ptzXml = new StringBuffer(200); | |
| 215 | - String charset = device.getCharset(); | |
| 216 | - ptzXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 217 | - ptzXml.append("<Control>\r\n"); | |
| 218 | - ptzXml.append("<CmdType>DeviceControl</CmdType>\r\n"); | |
| 219 | - ptzXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 220 | - ptzXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 221 | - ptzXml.append("<PTZCmd>" + cmdStr + "</PTZCmd>\r\n"); | |
| 222 | - ptzXml.append("<Info>\r\n"); | |
| 223 | - ptzXml.append("<ControlPriority>5</ControlPriority>\r\n"); | |
| 224 | - ptzXml.append("</Info>\r\n"); | |
| 225 | - ptzXml.append("</Control>\r\n"); | |
| 226 | - | |
| 227 | - | |
| 228 | - | |
| 229 | - | |
| 230 | - SIPRequest request = (SIPRequest) headerProvider.createMessageRequest(device, ptzXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 231 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()),request); | |
| 232 | - | |
| 233 | - } | |
| 234 | - | |
| 235 | - /** | |
| 236 | - * 前端控制指令(用于转发上级指令) | |
| 237 | - * | |
| 238 | - * @param device 控制设备 | |
| 239 | - * @param channelId 预览通道 | |
| 240 | - * @param cmdString 前端控制指令串 | |
| 241 | - */ | |
| 242 | - @Override | |
| 243 | - public void fronEndCmd(Device device, String channelId, String cmdString, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 244 | - | |
| 245 | - StringBuffer ptzXml = new StringBuffer(200); | |
| 246 | - String charset = device.getCharset(); | |
| 247 | - ptzXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 248 | - ptzXml.append("<Control>\r\n"); | |
| 249 | - ptzXml.append("<CmdType>DeviceControl</CmdType>\r\n"); | |
| 250 | - ptzXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 251 | - ptzXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 252 | - ptzXml.append("<PTZCmd>" + cmdString + "</PTZCmd>\r\n"); | |
| 253 | - ptzXml.append("<Info>\r\n"); | |
| 254 | - ptzXml.append("<ControlPriority>5</ControlPriority>\r\n"); | |
| 255 | - ptzXml.append("</Info>\r\n"); | |
| 256 | - ptzXml.append("</Control>\r\n"); | |
| 257 | - | |
| 258 | - | |
| 259 | - Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 260 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()),request, errorEvent, okEvent); | |
| 261 | - | |
| 262 | - } | |
| 263 | - | |
| 264 | - /** | |
| 265 | - * 请求预览视频流 | |
| 266 | - * | |
| 267 | - * @param device 视频设备 | |
| 268 | - * @param channel 预览通道 | |
| 269 | - * @param event hook订阅 | |
| 270 | - * @param errorEvent sip错误订阅 | |
| 271 | - */ | |
| 272 | - @Override | |
| 273 | - public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel, | |
| 274 | - ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 275 | - String stream = ssrcInfo.getStream(); | |
| 276 | - | |
| 277 | - if (device == null) { | |
| 278 | - return; | |
| 279 | - } | |
| 280 | - | |
| 281 | - logger.info("{} 分配的ZLM为: {} [{}:{}]", stream, mediaServerItem.getId(), mediaServerItem.getSdpIp(), ssrcInfo.getPort()); | |
| 282 | - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId()); | |
| 283 | - subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, HookParam hookParam) -> { | |
| 284 | - if (event != null) { | |
| 285 | - event.response(mediaServerItemInUse, hookParam); | |
| 286 | - subscribe.removeSubscribe(hookSubscribe); | |
| 287 | - } | |
| 288 | - }); | |
| 289 | - String sdpIp; | |
| 290 | - if (!ObjectUtils.isEmpty(device.getSdpIp())) { | |
| 291 | - sdpIp = device.getSdpIp(); | |
| 292 | - }else { | |
| 293 | - sdpIp = mediaServerItem.getSdpIp(); | |
| 294 | - } | |
| 295 | - StringBuffer content = new StringBuffer(200); | |
| 296 | - content.append("v=0\r\n"); | |
| 297 | - content.append("o=" + channel.getChannelId() + " 0 0 IN IP4 " + sdpIp + "\r\n"); | |
| 298 | - content.append("s=Play\r\n"); | |
| 299 | - content.append("c=IN IP4 " + sdpIp + "\r\n"); | |
| 300 | - content.append("t=0 0\r\n"); | |
| 301 | - | |
| 302 | - if (userSetting.isSeniorSdp()) { | |
| 303 | - if ("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) { | |
| 304 | - content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 126 125 99 34 98 97\r\n"); | |
| 305 | - } else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) { | |
| 306 | - content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 126 125 99 34 98 97\r\n"); | |
| 307 | - } else if ("UDP".equalsIgnoreCase(device.getStreamMode())) { | |
| 308 | - content.append("m=video " + ssrcInfo.getPort() + " RTP/AVP 96 126 125 99 34 98 97\r\n"); | |
| 309 | - } | |
| 310 | - content.append("a=recvonly\r\n"); | |
| 311 | - content.append("a=rtpmap:96 PS/90000\r\n"); | |
| 312 | - content.append("a=fmtp:126 profile-level-id=42e01e\r\n"); | |
| 313 | - content.append("a=rtpmap:126 H264/90000\r\n"); | |
| 314 | - content.append("a=rtpmap:125 H264S/90000\r\n"); | |
| 315 | - content.append("a=fmtp:125 profile-level-id=42e01e\r\n"); | |
| 316 | - content.append("a=rtpmap:99 H265/90000\r\n"); | |
| 317 | - content.append("a=rtpmap:98 H264/90000\r\n"); | |
| 318 | - content.append("a=rtpmap:97 MPEG4/90000\r\n"); | |
| 319 | - if ("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp被动模式 | |
| 320 | - content.append("a=setup:passive\r\n"); | |
| 321 | - content.append("a=connection:new\r\n"); | |
| 322 | - } else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp主动模式 | |
| 323 | - content.append("a=setup:active\r\n"); | |
| 324 | - content.append("a=connection:new\r\n"); | |
| 325 | - } | |
| 326 | - } else { | |
| 327 | - if ("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) { | |
| 328 | - content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 97 98 99\r\n"); | |
| 329 | - } else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) { | |
| 330 | - content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 97 98 99\r\n"); | |
| 331 | - } else if ("UDP".equalsIgnoreCase(device.getStreamMode())) { | |
| 332 | - content.append("m=video " + ssrcInfo.getPort() + " RTP/AVP 96 97 98 99\r\n"); | |
| 333 | - } | |
| 334 | - content.append("a=recvonly\r\n"); | |
| 335 | - content.append("a=rtpmap:96 PS/90000\r\n"); | |
| 336 | - content.append("a=rtpmap:98 H264/90000\r\n"); | |
| 337 | - content.append("a=rtpmap:97 MPEG4/90000\r\n"); | |
| 338 | - content.append("a=rtpmap:99 H265/90000\r\n"); | |
| 339 | - if ("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp被动模式 | |
| 340 | - content.append("a=setup:passive\r\n"); | |
| 341 | - content.append("a=connection:new\r\n"); | |
| 342 | - } else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp主动模式 | |
| 343 | - content.append("a=setup:active\r\n"); | |
| 344 | - content.append("a=connection:new\r\n"); | |
| 345 | - } | |
| 346 | - } | |
| 347 | - | |
| 348 | - if (!ObjectUtils.isEmpty(channel.getStreamIdentification())) { | |
| 349 | - content.append("a=" + channel.getStreamIdentification() + "\r\n"); | |
| 350 | - } | |
| 351 | - | |
| 352 | - content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc | |
| 353 | - // f字段:f= v/编码格式/分辨率/帧率/码率类型/码率大小a/编码格式/码率大小/采样率 | |
| 354 | -// content.append("f=v/2/5/25/1/4000a/1/8/1" + "\r\n"); // 未发现支持此特性的设备 | |
| 355 | - | |
| 356 | - | |
| 357 | - | |
| 358 | - Request request = headerProvider.createInviteRequest(device, channel.getChannelId(), content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 359 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> { | |
| 360 | - streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream()); | |
| 361 | - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | |
| 362 | - errorEvent.response(e); | |
| 363 | - }), e -> { | |
| 364 | - ResponseEvent responseEvent = (ResponseEvent) e.event; | |
| 365 | - SIPResponse response = (SIPResponse) responseEvent.getResponse(); | |
| 366 | - String callId = response.getCallIdHeader().getCallId(); | |
| 367 | - streamSession.put(device.getDeviceId(), channel.getChannelId(), callId, stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response, | |
| 368 | - InviteSessionType.PLAY); | |
| 369 | - okEvent.response(e); | |
| 370 | - }); | |
| 371 | - } | |
| 372 | - | |
| 373 | - /** | |
| 374 | - * 请求回放视频流 | |
| 375 | - * | |
| 376 | - * @param device 视频设备 | |
| 377 | - * @param channelId 预览通道 | |
| 378 | - * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss | |
| 379 | - * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss | |
| 380 | - */ | |
| 381 | - @Override | |
| 382 | - public void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, | |
| 383 | - String startTime, String endTime, ZlmHttpHookSubscribe.Event hookEvent, | |
| 384 | - SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 385 | - | |
| 386 | - | |
| 387 | - logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getSdpIp(), ssrcInfo.getPort()); | |
| 388 | - String sdpIp; | |
| 389 | - if (!ObjectUtils.isEmpty(device.getSdpIp())) { | |
| 390 | - sdpIp = device.getSdpIp(); | |
| 391 | - }else { | |
| 392 | - sdpIp = mediaServerItem.getSdpIp(); | |
| 393 | - } | |
| 394 | - StringBuffer content = new StringBuffer(200); | |
| 395 | - content.append("v=0\r\n"); | |
| 396 | - content.append("o=" + channelId + " 0 0 IN IP4 " + sdpIp + "\r\n"); | |
| 397 | - content.append("s=Playback\r\n"); | |
| 398 | - content.append("u=" + channelId + ":0\r\n"); | |
| 399 | - content.append("c=IN IP4 " + sdpIp + "\r\n"); | |
| 400 | - content.append("t=" + DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime) + " " | |
| 401 | - + DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) + "\r\n"); | |
| 402 | - | |
| 403 | - String streamMode = device.getStreamMode(); | |
| 404 | - | |
| 405 | - if (userSetting.isSeniorSdp()) { | |
| 406 | - if ("TCP-PASSIVE".equalsIgnoreCase(streamMode)) { | |
| 407 | - content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 126 125 99 34 98 97\r\n"); | |
| 408 | - } else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) { | |
| 409 | - content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 126 125 99 34 98 97\r\n"); | |
| 410 | - } else if ("UDP".equalsIgnoreCase(streamMode)) { | |
| 411 | - content.append("m=video " + ssrcInfo.getPort() + " RTP/AVP 96 126 125 99 34 98 97\r\n"); | |
| 412 | - } | |
| 413 | - content.append("a=recvonly\r\n"); | |
| 414 | - content.append("a=rtpmap:96 PS/90000\r\n"); | |
| 415 | - content.append("a=fmtp:126 profile-level-id=42e01e\r\n"); | |
| 416 | - content.append("a=rtpmap:126 H264/90000\r\n"); | |
| 417 | - content.append("a=rtpmap:125 H264S/90000\r\n"); | |
| 418 | - content.append("a=fmtp:125 profile-level-id=42e01e\r\n"); | |
| 419 | - content.append("a=rtpmap:99 H265/90000\r\n"); | |
| 420 | - content.append("a=rtpmap:98 H264/90000\r\n"); | |
| 421 | - content.append("a=rtpmap:97 MPEG4/90000\r\n"); | |
| 422 | - if ("TCP-PASSIVE".equalsIgnoreCase(streamMode)) { // tcp被动模式 | |
| 423 | - content.append("a=setup:passive\r\n"); | |
| 424 | - content.append("a=connection:new\r\n"); | |
| 425 | - } else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) { // tcp主动模式 | |
| 426 | - content.append("a=setup:active\r\n"); | |
| 427 | - content.append("a=connection:new\r\n"); | |
| 428 | - } | |
| 429 | - } else { | |
| 430 | - if ("TCP-PASSIVE".equalsIgnoreCase(streamMode)) { | |
| 431 | - content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 97 98 99\r\n"); | |
| 432 | - } else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) { | |
| 433 | - content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 97 98 99\r\n"); | |
| 434 | - } else if ("UDP".equalsIgnoreCase(streamMode)) { | |
| 435 | - content.append("m=video " + ssrcInfo.getPort() + " RTP/AVP 96 97 98 99\r\n"); | |
| 436 | - } | |
| 437 | - content.append("a=recvonly\r\n"); | |
| 438 | - content.append("a=rtpmap:96 PS/90000\r\n"); | |
| 439 | - content.append("a=rtpmap:97 MPEG4/90000\r\n"); | |
| 440 | - content.append("a=rtpmap:98 H264/90000\r\n"); | |
| 441 | - content.append("a=rtpmap:99 H265/90000\r\n"); | |
| 442 | - if ("TCP-PASSIVE".equalsIgnoreCase(streamMode)) { | |
| 443 | - // tcp被动模式 | |
| 444 | - content.append("a=setup:passive\r\n"); | |
| 445 | - content.append("a=connection:new\r\n"); | |
| 446 | - } else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) { | |
| 447 | - // tcp主动模式 | |
| 448 | - content.append("a=setup:active\r\n"); | |
| 449 | - content.append("a=connection:new\r\n"); | |
| 450 | - } | |
| 451 | - } | |
| 452 | - | |
| 453 | - //ssrc | |
| 454 | - content.append("y=" + ssrcInfo.getSsrc() + "\r\n"); | |
| 455 | - | |
| 456 | - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId()); | |
| 457 | - // 添加订阅 | |
| 458 | - subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, HookParam hookParam) -> { | |
| 459 | - if (hookEvent != null) { | |
| 460 | - hookEvent.response(mediaServerItemInUse, hookParam); | |
| 461 | - } | |
| 462 | - subscribe.removeSubscribe(hookSubscribe); | |
| 463 | - }); | |
| 464 | - Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()), ssrcInfo.getSsrc()); | |
| 465 | - | |
| 466 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, event -> { | |
| 467 | - ResponseEvent responseEvent = (ResponseEvent) event.event; | |
| 468 | - SIPResponse response = (SIPResponse) responseEvent.getResponse(); | |
| 469 | - streamSession.put(device.getDeviceId(), channelId,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response, InviteSessionType.PLAYBACK); | |
| 470 | - okEvent.response(event); | |
| 471 | - }); | |
| 472 | - } | |
| 473 | - | |
| 474 | - /** | |
| 475 | - * 请求历史媒体下载 | |
| 476 | - * | |
| 477 | - * @param device 视频设备 | |
| 478 | - * @param channelId 预览通道 | |
| 479 | - * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss | |
| 480 | - * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss | |
| 481 | - * @param downloadSpeed 下载倍速参数 | |
| 482 | - */ | |
| 483 | - @Override | |
| 484 | - public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, | |
| 485 | - String startTime, String endTime, int downloadSpeed, | |
| 486 | - ZlmHttpHookSubscribe.Event hookEvent, | |
| 487 | - SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 488 | - | |
| 489 | - logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getSdpIp(), ssrcInfo.getPort()); | |
| 490 | - String sdpIp; | |
| 491 | - if (!ObjectUtils.isEmpty(device.getSdpIp())) { | |
| 492 | - sdpIp = device.getSdpIp(); | |
| 493 | - }else { | |
| 494 | - sdpIp = mediaServerItem.getSdpIp(); | |
| 495 | - } | |
| 496 | - StringBuffer content = new StringBuffer(200); | |
| 497 | - content.append("v=0\r\n"); | |
| 498 | - content.append("o=" + channelId + " 0 0 IN IP4 " + sdpIp + "\r\n"); | |
| 499 | - content.append("s=Download\r\n"); | |
| 500 | - content.append("u=" + channelId + ":0\r\n"); | |
| 501 | - content.append("c=IN IP4 " + sdpIp + "\r\n"); | |
| 502 | - content.append("t=" + DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime) + " " | |
| 503 | - + DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) + "\r\n"); | |
| 504 | - | |
| 505 | - String streamMode = device.getStreamMode().toUpperCase(); | |
| 506 | - | |
| 507 | - if (userSetting.isSeniorSdp()) { | |
| 508 | - if ("TCP-PASSIVE".equals(streamMode)) { | |
| 509 | - content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 126 125 99 34 98 97\r\n"); | |
| 510 | - } else if ("TCP-ACTIVE".equals(streamMode)) { | |
| 511 | - content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 126 125 99 34 98 97\r\n"); | |
| 512 | - } else if ("UDP".equals(streamMode)) { | |
| 513 | - content.append("m=video " + ssrcInfo.getPort() + " RTP/AVP 96 126 125 99 34 98 97\r\n"); | |
| 514 | - } | |
| 515 | - content.append("a=recvonly\r\n"); | |
| 516 | - content.append("a=rtpmap:96 PS/90000\r\n"); | |
| 517 | - content.append("a=fmtp:126 profile-level-id=42e01e\r\n"); | |
| 518 | - content.append("a=rtpmap:126 H264/90000\r\n"); | |
| 519 | - content.append("a=rtpmap:125 H264S/90000\r\n"); | |
| 520 | - content.append("a=fmtp:125 profile-level-id=42e01e\r\n"); | |
| 521 | - content.append("a=rtpmap:99 MP4V-ES/90000\r\n"); | |
| 522 | - content.append("a=fmtp:99 profile-level-id=3\r\n"); | |
| 523 | - content.append("a=rtpmap:98 H264/90000\r\n"); | |
| 524 | - content.append("a=rtpmap:97 MPEG4/90000\r\n"); | |
| 525 | - if ("TCP-PASSIVE".equals(streamMode)) { // tcp被动模式 | |
| 526 | - content.append("a=setup:passive\r\n"); | |
| 527 | - content.append("a=connection:new\r\n"); | |
| 528 | - } else if ("TCP-ACTIVE".equals(streamMode)) { // tcp主动模式 | |
| 529 | - content.append("a=setup:active\r\n"); | |
| 530 | - content.append("a=connection:new\r\n"); | |
| 531 | - } | |
| 532 | - } else { | |
| 533 | - if ("TCP-PASSIVE".equals(streamMode)) { | |
| 534 | - content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 97 98 99\r\n"); | |
| 535 | - } else if ("TCP-ACTIVE".equals(streamMode)) { | |
| 536 | - content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 97 98 99\r\n"); | |
| 537 | - } else if ("UDP".equals(streamMode)) { | |
| 538 | - content.append("m=video " + ssrcInfo.getPort() + " RTP/AVP 96 97 98 99\r\n"); | |
| 539 | - } | |
| 540 | - content.append("a=recvonly\r\n"); | |
| 541 | - content.append("a=rtpmap:96 PS/90000\r\n"); | |
| 542 | - content.append("a=rtpmap:97 MPEG4/90000\r\n"); | |
| 543 | - content.append("a=rtpmap:98 H264/90000\r\n"); | |
| 544 | - content.append("a=rtpmap:99 H265/90000\r\n"); | |
| 545 | - if ("TCP-PASSIVE".equals(streamMode)) { // tcp被动模式 | |
| 546 | - content.append("a=setup:passive\r\n"); | |
| 547 | - content.append("a=connection:new\r\n"); | |
| 548 | - } else if ("TCP-ACTIVE".equals(streamMode)) { // tcp主动模式 | |
| 549 | - content.append("a=setup:active\r\n"); | |
| 550 | - content.append("a=connection:new\r\n"); | |
| 551 | - } | |
| 552 | - } | |
| 553 | - content.append("a=downloadspeed:" + downloadSpeed + "\r\n"); | |
| 554 | - | |
| 555 | - content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc | |
| 556 | - logger.debug("此时请求下载信令的ssrc===>{}",ssrcInfo.getSsrc()); | |
| 557 | - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId()); | |
| 558 | - // 添加订阅 | |
| 559 | - CallIdHeader newCallIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()), device.getTransport()); | |
| 560 | - String callId= newCallIdHeader.getCallId(); | |
| 561 | - subscribe.addSubscribe(hookSubscribe, (mediaServerItemInUse, hookParam) -> { | |
| 562 | - logger.debug("sipc 添加订阅===callId {}",callId); | |
| 563 | - hookEvent.response(mediaServerItemInUse, hookParam); | |
| 564 | - subscribe.removeSubscribe(hookSubscribe); | |
| 565 | - hookSubscribe.getContent().put("regist", false); | |
| 566 | - hookSubscribe.getContent().put("schema", "rtsp"); | |
| 567 | - // 添加流注销的订阅,注销了后向设备发送bye | |
| 568 | - subscribe.addSubscribe(hookSubscribe, | |
| 569 | - (mediaServerItemForEnd, hookParam1) -> { | |
| 570 | - logger.info("[录像]下载结束, 发送BYE"); | |
| 571 | - try { | |
| 572 | - streamByeCmd(device, channelId, ssrcInfo.getStream(), callId); | |
| 573 | - } catch (InvalidArgumentException | ParseException | SipException | | |
| 574 | - SsrcTransactionNotFoundException e) { | |
| 575 | - logger.error("[录像]下载结束, 发送BYE失败 {}", e.getMessage()); | |
| 576 | - } | |
| 577 | - }); | |
| 578 | - }); | |
| 579 | - | |
| 580 | - Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,newCallIdHeader, ssrcInfo.getSsrc()); | |
| 581 | - | |
| 582 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, event -> { | |
| 583 | - ResponseEvent responseEvent = (ResponseEvent) event.event; | |
| 584 | - SIPResponse response = (SIPResponse) responseEvent.getResponse(); | |
| 585 | - String contentString =new String(response.getRawContent()); | |
| 586 | - String ssrc = SipUtils.getSsrcFromSdp(contentString); | |
| 587 | - streamSession.put(device.getDeviceId(), channelId, response.getCallIdHeader().getCallId(), ssrcInfo.getStream(), ssrc, mediaServerItem.getId(), response, InviteSessionType.DOWNLOAD); | |
| 588 | - okEvent.response(event); | |
| 589 | - }); | |
| 590 | - } | |
| 591 | - | |
| 592 | - /** | |
| 593 | - * 视频流停止, 不使用回调 | |
| 594 | - */ | |
| 595 | - @Override | |
| 596 | - public void streamByeCmd(Device device, String channelId, String stream, String callId) throws InvalidArgumentException, ParseException, SipException, SsrcTransactionNotFoundException { | |
| 597 | - streamByeCmd(device, channelId, stream, callId, null); | |
| 598 | - } | |
| 599 | - | |
| 600 | - /** | |
| 601 | - * 视频流停止 | |
| 602 | - */ | |
| 603 | - @Override | |
| 604 | - public void streamByeCmd(Device device, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException { | |
| 605 | - if (device == null) { | |
| 606 | - logger.warn("[发送BYE] device为null"); | |
| 607 | - return; | |
| 608 | - } | |
| 609 | - List<SsrcTransaction> ssrcTransactionList = streamSession.getSsrcTransactionForAll(device.getDeviceId(), channelId, callId, stream); | |
| 610 | - if (ssrcTransactionList == null || ssrcTransactionList.isEmpty()) { | |
| 611 | - logger.info("[发送BYE] 未找到事务信息,设备: device: {}, channel: {}", device.getDeviceId(), channelId); | |
| 612 | - throw new SsrcTransactionNotFoundException(device.getDeviceId(), channelId, callId, stream); | |
| 613 | - } | |
| 614 | - | |
| 615 | - for (SsrcTransaction ssrcTransaction : ssrcTransactionList) { | |
| 616 | - logger.info("[发送BYE] 设备: device: {}, channel: {}, callId: {}", device.getDeviceId(), channelId, ssrcTransaction.getCallId()); | |
| 617 | - mediaServerService.releaseSsrc(ssrcTransaction.getMediaServerId(), ssrcTransaction.getSsrc()); | |
| 618 | - | |
| 619 | - mediaServerService.closeRTPServer(ssrcTransaction.getMediaServerId(), ssrcTransaction.getStream()); | |
| 620 | - streamSession.removeByCallId(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId(), ssrcTransaction.getCallId()); | |
| 621 | - Request byteRequest = headerProvider.createByteRequest(device, channelId, ssrcTransaction.getSipTransactionInfo()); | |
| 622 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), byteRequest, null, okEvent); | |
| 623 | - | |
| 624 | - } | |
| 625 | - } | |
| 626 | - | |
| 627 | - /** | |
| 628 | - * 语音广播 | |
| 629 | - * | |
| 630 | - * @param device 视频设备 | |
| 631 | - * @param channelId 预览通道 | |
| 632 | - */ | |
| 633 | - @Override | |
| 634 | - public void audioBroadcastCmd(Device device, String channelId) { | |
| 635 | - } | |
| 636 | - | |
| 637 | - /** | |
| 638 | - * 语音广播 | |
| 639 | - * | |
| 640 | - * @param device 视频设备 | |
| 641 | - */ | |
| 642 | - @Override | |
| 643 | - public void audioBroadcastCmd(Device device) throws InvalidArgumentException, SipException, ParseException { | |
| 644 | - | |
| 645 | - StringBuffer broadcastXml = new StringBuffer(200); | |
| 646 | - String charset = device.getCharset(); | |
| 647 | - broadcastXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 648 | - broadcastXml.append("<Notify>\r\n"); | |
| 649 | - broadcastXml.append("<CmdType>Broadcast</CmdType>\r\n"); | |
| 650 | - broadcastXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 651 | - broadcastXml.append("<SourceID>" + sipConfig.getId() + "</SourceID>\r\n"); | |
| 652 | - broadcastXml.append("<TargetID>" + device.getDeviceId() + "</TargetID>\r\n"); | |
| 653 | - broadcastXml.append("</Notify>\r\n"); | |
| 654 | - | |
| 655 | - | |
| 656 | - | |
| 657 | - Request request = headerProvider.createMessageRequest(device, broadcastXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 658 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request); | |
| 659 | - | |
| 660 | - } | |
| 661 | - | |
| 662 | - @Override | |
| 663 | - public void audioBroadcastCmd(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 664 | - | |
| 665 | - StringBuffer broadcastXml = new StringBuffer(200); | |
| 666 | - String charset = device.getCharset(); | |
| 667 | - broadcastXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 668 | - broadcastXml.append("<Notify>\r\n"); | |
| 669 | - broadcastXml.append("<CmdType>Broadcast</CmdType>\r\n"); | |
| 670 | - broadcastXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 671 | - broadcastXml.append("<SourceID>" + sipConfig.getId() + "</SourceID>\r\n"); | |
| 672 | - broadcastXml.append("<TargetID>" + device.getDeviceId() + "</TargetID>\r\n"); | |
| 673 | - broadcastXml.append("</Notify>\r\n"); | |
| 674 | - | |
| 675 | - | |
| 676 | - | |
| 677 | - Request request = headerProvider.createMessageRequest(device, broadcastXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 678 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); | |
| 679 | - | |
| 680 | - } | |
| 681 | - | |
| 682 | - | |
| 683 | - /** | |
| 684 | - * 音视频录像控制 | |
| 685 | - * | |
| 686 | - * @param device 视频设备 | |
| 687 | - * @param channelId 预览通道 | |
| 688 | - * @param recordCmdStr 录像命令:Record / StopRecord | |
| 689 | - */ | |
| 690 | - @Override | |
| 691 | - public void recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 692 | - StringBuffer cmdXml = new StringBuffer(200); | |
| 693 | - String charset = device.getCharset(); | |
| 694 | - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 695 | - cmdXml.append("<Control>\r\n"); | |
| 696 | - cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n"); | |
| 697 | - cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 698 | - if (ObjectUtils.isEmpty(channelId)) { | |
| 699 | - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 700 | - } else { | |
| 701 | - cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 702 | - } | |
| 703 | - cmdXml.append("<RecordCmd>" + recordCmdStr + "</RecordCmd>\r\n"); | |
| 704 | - cmdXml.append("</Control>\r\n"); | |
| 705 | - | |
| 706 | - | |
| 707 | - | |
| 708 | - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 709 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent); | |
| 710 | - } | |
| 711 | - | |
| 712 | - /** | |
| 713 | - * 远程启动控制命令 | |
| 714 | - * | |
| 715 | - * @param device 视频设备 | |
| 716 | - */ | |
| 717 | - @Override | |
| 718 | - public void teleBootCmd(Device device) throws InvalidArgumentException, SipException, ParseException { | |
| 719 | - | |
| 720 | - StringBuffer cmdXml = new StringBuffer(200); | |
| 721 | - String charset = device.getCharset(); | |
| 722 | - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 723 | - cmdXml.append("<Control>\r\n"); | |
| 724 | - cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n"); | |
| 725 | - cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 726 | - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 727 | - cmdXml.append("<TeleBoot>Boot</TeleBoot>\r\n"); | |
| 728 | - cmdXml.append("</Control>\r\n"); | |
| 729 | - | |
| 730 | - | |
| 731 | - | |
| 732 | - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 733 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request); | |
| 734 | - } | |
| 735 | - | |
| 736 | - /** | |
| 737 | - * 报警布防/撤防命令 | |
| 738 | - * | |
| 739 | - * @param device 视频设备 | |
| 740 | - * @param guardCmdStr "SetGuard"/"ResetGuard" | |
| 741 | - */ | |
| 742 | - @Override | |
| 743 | - public void guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 744 | - | |
| 745 | - StringBuffer cmdXml = new StringBuffer(200); | |
| 746 | - String charset = device.getCharset(); | |
| 747 | - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 748 | - cmdXml.append("<Control>\r\n"); | |
| 749 | - cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n"); | |
| 750 | - cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 751 | - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 752 | - cmdXml.append("<GuardCmd>" + guardCmdStr + "</GuardCmd>\r\n"); | |
| 753 | - cmdXml.append("</Control>\r\n"); | |
| 754 | - | |
| 755 | - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 756 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent); | |
| 757 | - } | |
| 758 | - | |
| 759 | - /** | |
| 760 | - * 报警复位命令 | |
| 761 | - * | |
| 762 | - * @param device 视频设备 | |
| 763 | - */ | |
| 764 | - @Override | |
| 765 | - public void alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 766 | - | |
| 767 | - StringBuffer cmdXml = new StringBuffer(200); | |
| 768 | - String charset = device.getCharset(); | |
| 769 | - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 770 | - cmdXml.append("<Control>\r\n"); | |
| 771 | - cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n"); | |
| 772 | - cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 773 | - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 774 | - cmdXml.append("<AlarmCmd>ResetAlarm</AlarmCmd>\r\n"); | |
| 775 | - if (!ObjectUtils.isEmpty(alarmMethod) || !ObjectUtils.isEmpty(alarmType)) { | |
| 776 | - cmdXml.append("<Info>\r\n"); | |
| 777 | - } | |
| 778 | - if (!ObjectUtils.isEmpty(alarmMethod)) { | |
| 779 | - cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n"); | |
| 780 | - } | |
| 781 | - if (!ObjectUtils.isEmpty(alarmType)) { | |
| 782 | - cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n"); | |
| 783 | - } | |
| 784 | - if (!ObjectUtils.isEmpty(alarmMethod) || !ObjectUtils.isEmpty(alarmType)) { | |
| 785 | - cmdXml.append("</Info>\r\n"); | |
| 786 | - } | |
| 787 | - cmdXml.append("</Control>\r\n"); | |
| 788 | - | |
| 789 | - | |
| 790 | - | |
| 791 | - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 792 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent); | |
| 793 | - } | |
| 794 | - | |
| 795 | - /** | |
| 796 | - * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧 | |
| 797 | - * | |
| 798 | - * @param device 视频设备 | |
| 799 | - * @param channelId 预览通道 | |
| 800 | - */ | |
| 801 | - @Override | |
| 802 | - public void iFrameCmd(Device device, String channelId) throws InvalidArgumentException, SipException, ParseException { | |
| 803 | - | |
| 804 | - StringBuffer cmdXml = new StringBuffer(200); | |
| 805 | - String charset = device.getCharset(); | |
| 806 | - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 807 | - cmdXml.append("<Control>\r\n"); | |
| 808 | - cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n"); | |
| 809 | - cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 810 | - if (ObjectUtils.isEmpty(channelId)) { | |
| 811 | - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 812 | - } else { | |
| 813 | - cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 814 | - } | |
| 815 | - cmdXml.append("<IFameCmd>Send</IFameCmd>\r\n"); | |
| 816 | - cmdXml.append("</Control>\r\n"); | |
| 817 | - | |
| 818 | - | |
| 819 | - | |
| 820 | - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 821 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request); | |
| 822 | - } | |
| 823 | - | |
| 824 | - /** | |
| 825 | - * 看守位控制命令 | |
| 826 | - * | |
| 827 | - * @param device 视频设备 | |
| 828 | - * @param channelId 通道id,非通道则是设备本身 | |
| 829 | - * @param enabled 看守位使能:1 = 开启,0 = 关闭 | |
| 830 | - * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s) | |
| 831 | - * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255 | |
| 832 | - */ | |
| 833 | - @Override | |
| 834 | - public void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 835 | - | |
| 836 | - StringBuffer cmdXml = new StringBuffer(200); | |
| 837 | - String charset = device.getCharset(); | |
| 838 | - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 839 | - cmdXml.append("<Control>\r\n"); | |
| 840 | - cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n"); | |
| 841 | - cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 842 | - if (ObjectUtils.isEmpty(channelId)) { | |
| 843 | - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 844 | - } else { | |
| 845 | - cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 846 | - } | |
| 847 | - cmdXml.append("<HomePosition>\r\n"); | |
| 848 | - if (NumericUtil.isInteger(enabled) && (!enabled.equals("0"))) { | |
| 849 | - cmdXml.append("<Enabled>1</Enabled>\r\n"); | |
| 850 | - if (NumericUtil.isInteger(resetTime)) { | |
| 851 | - cmdXml.append("<ResetTime>" + resetTime + "</ResetTime>\r\n"); | |
| 852 | - } else { | |
| 853 | - cmdXml.append("<ResetTime>0</ResetTime>\r\n"); | |
| 854 | - } | |
| 855 | - if (NumericUtil.isInteger(presetIndex)) { | |
| 856 | - cmdXml.append("<PresetIndex>" + presetIndex + "</PresetIndex>\r\n"); | |
| 857 | - } else { | |
| 858 | - cmdXml.append("<PresetIndex>0</PresetIndex>\r\n"); | |
| 859 | - } | |
| 860 | - } else { | |
| 861 | - cmdXml.append("<Enabled>0</Enabled>\r\n"); | |
| 862 | - } | |
| 863 | - cmdXml.append("</HomePosition>\r\n"); | |
| 864 | - cmdXml.append("</Control>\r\n"); | |
| 865 | - | |
| 866 | - | |
| 867 | - | |
| 868 | - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 869 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent); | |
| 870 | - } | |
| 871 | - | |
| 872 | - /** | |
| 873 | - * 设备配置命令 | |
| 874 | - * | |
| 875 | - * @param device 视频设备 | |
| 876 | - */ | |
| 877 | - @Override | |
| 878 | - public void deviceConfigCmd(Device device) { | |
| 879 | - // TODO Auto-generated method stub | |
| 880 | - } | |
| 881 | - | |
| 882 | - /** | |
| 883 | - * 设备配置命令:basicParam | |
| 884 | - * | |
| 885 | - * @param device 视频设备 | |
| 886 | - * @param channelId 通道编码(可选) | |
| 887 | - * @param name 设备/通道名称(可选) | |
| 888 | - * @param expiration 注册过期时间(可选) | |
| 889 | - * @param heartBeatInterval 心跳间隔时间(可选) | |
| 890 | - * @param heartBeatCount 心跳超时次数(可选) | |
| 891 | - */ | |
| 892 | - @Override | |
| 893 | - public void deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, | |
| 894 | - String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 895 | - | |
| 896 | - StringBuffer cmdXml = new StringBuffer(200); | |
| 897 | - String charset = device.getCharset(); | |
| 898 | - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 899 | - cmdXml.append("<Control>\r\n"); | |
| 900 | - cmdXml.append("<CmdType>DeviceConfig</CmdType>\r\n"); | |
| 901 | - cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 902 | - if (ObjectUtils.isEmpty(channelId)) { | |
| 903 | - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 904 | - } else { | |
| 905 | - cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 906 | - } | |
| 907 | - cmdXml.append("<BasicParam>\r\n"); | |
| 908 | - if (!ObjectUtils.isEmpty(name)) { | |
| 909 | - cmdXml.append("<Name>" + name + "</Name>\r\n"); | |
| 910 | - } | |
| 911 | - if (NumericUtil.isInteger(expiration)) { | |
| 912 | - if (Integer.valueOf(expiration) > 0) { | |
| 913 | - cmdXml.append("<Expiration>" + expiration + "</Expiration>\r\n"); | |
| 914 | - } | |
| 915 | - } | |
| 916 | - if (NumericUtil.isInteger(heartBeatInterval)) { | |
| 917 | - if (Integer.valueOf(heartBeatInterval) > 0) { | |
| 918 | - cmdXml.append("<HeartBeatInterval>" + heartBeatInterval + "</HeartBeatInterval>\r\n"); | |
| 919 | - } | |
| 920 | - } | |
| 921 | - if (NumericUtil.isInteger(heartBeatCount)) { | |
| 922 | - if (Integer.valueOf(heartBeatCount) > 0) { | |
| 923 | - cmdXml.append("<HeartBeatCount>" + heartBeatCount + "</HeartBeatCount>\r\n"); | |
| 924 | - } | |
| 925 | - } | |
| 926 | - cmdXml.append("</BasicParam>\r\n"); | |
| 927 | - cmdXml.append("</Control>\r\n"); | |
| 928 | - | |
| 929 | - | |
| 930 | - | |
| 931 | - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 932 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); | |
| 933 | - } | |
| 934 | - | |
| 935 | - /** | |
| 936 | - * 查询设备状态 | |
| 937 | - * | |
| 938 | - * @param device 视频设备 | |
| 939 | - */ | |
| 940 | - @Override | |
| 941 | - public void deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 942 | - | |
| 943 | - String charset = device.getCharset(); | |
| 944 | - StringBuffer catalogXml = new StringBuffer(200); | |
| 945 | - catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 946 | - catalogXml.append("<Query>\r\n"); | |
| 947 | - catalogXml.append("<CmdType>DeviceStatus</CmdType>\r\n"); | |
| 948 | - catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 949 | - catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 950 | - catalogXml.append("</Query>\r\n"); | |
| 951 | - | |
| 952 | - Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 953 | - | |
| 954 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); | |
| 955 | - } | |
| 956 | - | |
| 957 | - /** | |
| 958 | - * 查询设备信息 | |
| 959 | - * | |
| 960 | - * @param device 视频设备 | |
| 961 | - */ | |
| 962 | - @Override | |
| 963 | - public void deviceInfoQuery(Device device) throws InvalidArgumentException, SipException, ParseException { | |
| 964 | - | |
| 965 | - StringBuffer catalogXml = new StringBuffer(200); | |
| 966 | - String charset = device.getCharset(); | |
| 967 | - catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 968 | - catalogXml.append("<Query>\r\n"); | |
| 969 | - catalogXml.append("<CmdType>DeviceInfo</CmdType>\r\n"); | |
| 970 | - catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 971 | - catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 972 | - catalogXml.append("</Query>\r\n"); | |
| 973 | - | |
| 974 | - | |
| 975 | - | |
| 976 | - Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 977 | - | |
| 978 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request); | |
| 979 | - | |
| 980 | - } | |
| 981 | - | |
| 982 | - /** | |
| 983 | - * 查询目录列表 | |
| 984 | - * | |
| 985 | - * @param device 视频设备 | |
| 986 | - */ | |
| 987 | - @Override | |
| 988 | - public void catalogQuery(Device device, int sn, SipSubscribe.Event errorEvent) throws SipException, InvalidArgumentException, ParseException { | |
| 989 | - | |
| 990 | - StringBuffer catalogXml = new StringBuffer(200); | |
| 991 | - String charset = device.getCharset(); | |
| 992 | - catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 993 | - catalogXml.append("<Query>\r\n"); | |
| 994 | - catalogXml.append(" <CmdType>Catalog</CmdType>\r\n"); | |
| 995 | - catalogXml.append(" <SN>" + sn + "</SN>\r\n"); | |
| 996 | - catalogXml.append(" <DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 997 | - catalogXml.append("</Query>\r\n"); | |
| 998 | - | |
| 999 | - | |
| 1000 | - | |
| 1001 | - Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 1002 | - | |
| 1003 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); | |
| 1004 | - } | |
| 1005 | - | |
| 1006 | - /** | |
| 1007 | - * 查询录像信息 | |
| 1008 | - * | |
| 1009 | - * @param device 视频设备 | |
| 1010 | - * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss | |
| 1011 | - * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss | |
| 1012 | - */ | |
| 1013 | - @Override | |
| 1014 | - public void recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, Integer secrecy, String type, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 1015 | - if (secrecy == null) { | |
| 1016 | - secrecy = 0; | |
| 1017 | - } | |
| 1018 | - if (type == null) { | |
| 1019 | - type = "all"; | |
| 1020 | - } | |
| 1021 | - | |
| 1022 | - StringBuffer recordInfoXml = new StringBuffer(200); | |
| 1023 | - String charset = device.getCharset(); | |
| 1024 | - recordInfoXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 1025 | - recordInfoXml.append("<Query>\r\n"); | |
| 1026 | - recordInfoXml.append("<CmdType>RecordInfo</CmdType>\r\n"); | |
| 1027 | - recordInfoXml.append("<SN>" + sn + "</SN>\r\n"); | |
| 1028 | - recordInfoXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 1029 | - if (startTime != null) { | |
| 1030 | - recordInfoXml.append("<StartTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(startTime) + "</StartTime>\r\n"); | |
| 1031 | - } | |
| 1032 | - if (endTime != null) { | |
| 1033 | - recordInfoXml.append("<EndTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(endTime) + "</EndTime>\r\n"); | |
| 1034 | - } | |
| 1035 | - if (secrecy != null) { | |
| 1036 | - recordInfoXml.append("<Secrecy> " + secrecy + " </Secrecy>\r\n"); | |
| 1037 | - } | |
| 1038 | - if (type != null) { | |
| 1039 | - // 大华NVR要求必须增加一个值为all的文本元素节点Type | |
| 1040 | - recordInfoXml.append("<Type>" + type + "</Type>\r\n"); | |
| 1041 | - } | |
| 1042 | - recordInfoXml.append("</Query>\r\n"); | |
| 1043 | - | |
| 1044 | - | |
| 1045 | - | |
| 1046 | - Request request = headerProvider.createMessageRequest(device, recordInfoXml.toString(), | |
| 1047 | - SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 1048 | - | |
| 1049 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, okEvent); | |
| 1050 | - } | |
| 1051 | - | |
| 1052 | - /** | |
| 1053 | - * 查询报警信息 | |
| 1054 | - * | |
| 1055 | - * @param device 视频设备 | |
| 1056 | - * @param startPriority 报警起始级别(可选) | |
| 1057 | - * @param endPriority 报警终止级别(可选) | |
| 1058 | - * @param alarmMethod 报警方式条件(可选) | |
| 1059 | - * @param alarmType 报警类型 | |
| 1060 | - * @param startTime 报警发生起始时间(可选) | |
| 1061 | - * @param endTime 报警发生终止时间(可选) | |
| 1062 | - * @return true = 命令发送成功 | |
| 1063 | - */ | |
| 1064 | - @Override | |
| 1065 | - public void alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod, String alarmType, | |
| 1066 | - String startTime, String endTime, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 1067 | - | |
| 1068 | - StringBuffer cmdXml = new StringBuffer(200); | |
| 1069 | - String charset = device.getCharset(); | |
| 1070 | - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 1071 | - cmdXml.append("<Query>\r\n"); | |
| 1072 | - cmdXml.append("<CmdType>Alarm</CmdType>\r\n"); | |
| 1073 | - cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 1074 | - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 1075 | - if (!ObjectUtils.isEmpty(startPriority)) { | |
| 1076 | - cmdXml.append("<StartAlarmPriority>" + startPriority + "</StartAlarmPriority>\r\n"); | |
| 1077 | - } | |
| 1078 | - if (!ObjectUtils.isEmpty(endPriority)) { | |
| 1079 | - cmdXml.append("<EndAlarmPriority>" + endPriority + "</EndAlarmPriority>\r\n"); | |
| 1080 | - } | |
| 1081 | - if (!ObjectUtils.isEmpty(alarmMethod)) { | |
| 1082 | - cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n"); | |
| 1083 | - } | |
| 1084 | - if (!ObjectUtils.isEmpty(alarmType)) { | |
| 1085 | - cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n"); | |
| 1086 | - } | |
| 1087 | - if (!ObjectUtils.isEmpty(startTime)) { | |
| 1088 | - cmdXml.append("<StartAlarmTime>" + startTime + "</StartAlarmTime>\r\n"); | |
| 1089 | - } | |
| 1090 | - if (!ObjectUtils.isEmpty(endTime)) { | |
| 1091 | - cmdXml.append("<EndAlarmTime>" + endTime + "</EndAlarmTime>\r\n"); | |
| 1092 | - } | |
| 1093 | - cmdXml.append("</Query>\r\n"); | |
| 1094 | - | |
| 1095 | - | |
| 1096 | - | |
| 1097 | - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 1098 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); | |
| 1099 | - } | |
| 1100 | - | |
| 1101 | - /** | |
| 1102 | - * 查询设备配置 | |
| 1103 | - * | |
| 1104 | - * @param device 视频设备 | |
| 1105 | - * @param channelId 通道编码(可选) | |
| 1106 | - * @param configType 配置类型: | |
| 1107 | - */ | |
| 1108 | - @Override | |
| 1109 | - public void deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 1110 | - | |
| 1111 | - StringBuffer cmdXml = new StringBuffer(200); | |
| 1112 | - String charset = device.getCharset(); | |
| 1113 | - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 1114 | - cmdXml.append("<Query>\r\n"); | |
| 1115 | - cmdXml.append("<CmdType>ConfigDownload</CmdType>\r\n"); | |
| 1116 | - cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 1117 | - if (ObjectUtils.isEmpty(channelId)) { | |
| 1118 | - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 1119 | - } else { | |
| 1120 | - cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 1121 | - } | |
| 1122 | - cmdXml.append("<ConfigType>" + configType + "</ConfigType>\r\n"); | |
| 1123 | - cmdXml.append("</Query>\r\n"); | |
| 1124 | - | |
| 1125 | - | |
| 1126 | - | |
| 1127 | - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 1128 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); | |
| 1129 | - } | |
| 1130 | - | |
| 1131 | - /** | |
| 1132 | - * 查询设备预置位置 | |
| 1133 | - * | |
| 1134 | - * @param device 视频设备 | |
| 1135 | - */ | |
| 1136 | - @Override | |
| 1137 | - public void presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 1138 | - | |
| 1139 | - StringBuffer cmdXml = new StringBuffer(200); | |
| 1140 | - String charset = device.getCharset(); | |
| 1141 | - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 1142 | - cmdXml.append("<Query>\r\n"); | |
| 1143 | - cmdXml.append("<CmdType>PresetQuery</CmdType>\r\n"); | |
| 1144 | - cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 1145 | - if (ObjectUtils.isEmpty(channelId)) { | |
| 1146 | - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 1147 | - } else { | |
| 1148 | - cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 1149 | - } | |
| 1150 | - cmdXml.append("</Query>\r\n"); | |
| 1151 | - | |
| 1152 | - | |
| 1153 | - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 1154 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); | |
| 1155 | - } | |
| 1156 | - | |
| 1157 | - /** | |
| 1158 | - * 查询移动设备位置数据 | |
| 1159 | - * | |
| 1160 | - * @param device 视频设备 | |
| 1161 | - */ | |
| 1162 | - @Override | |
| 1163 | - public void mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 1164 | - | |
| 1165 | - StringBuffer mobilePostitionXml = new StringBuffer(200); | |
| 1166 | - String charset = device.getCharset(); | |
| 1167 | - mobilePostitionXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 1168 | - mobilePostitionXml.append("<Query>\r\n"); | |
| 1169 | - mobilePostitionXml.append("<CmdType>MobilePosition</CmdType>\r\n"); | |
| 1170 | - mobilePostitionXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 1171 | - mobilePostitionXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 1172 | - mobilePostitionXml.append("<Interval>60</Interval>\r\n"); | |
| 1173 | - mobilePostitionXml.append("</Query>\r\n"); | |
| 1174 | - | |
| 1175 | - | |
| 1176 | - | |
| 1177 | - Request request = headerProvider.createMessageRequest(device, mobilePostitionXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 1178 | - | |
| 1179 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); | |
| 1180 | - | |
| 1181 | - } | |
| 1182 | - | |
| 1183 | - /** | |
| 1184 | - * 订阅、取消订阅移动位置 | |
| 1185 | - * | |
| 1186 | - * @param device 视频设备 | |
| 1187 | - * @return true = 命令发送成功 | |
| 1188 | - */ | |
| 1189 | - @Override | |
| 1190 | - public SIPRequest mobilePositionSubscribe(Device device, SIPRequest requestOld, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 1191 | - | |
| 1192 | - StringBuffer subscribePostitionXml = new StringBuffer(200); | |
| 1193 | - String charset = device.getCharset(); | |
| 1194 | - subscribePostitionXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 1195 | - subscribePostitionXml.append("<Query>\r\n"); | |
| 1196 | - subscribePostitionXml.append("<CmdType>MobilePosition</CmdType>\r\n"); | |
| 1197 | - subscribePostitionXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 1198 | - subscribePostitionXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 1199 | - if (device.getSubscribeCycleForMobilePosition() > 0) { | |
| 1200 | - subscribePostitionXml.append("<Interval>" + device.getMobilePositionSubmissionInterval() + "</Interval>\r\n"); | |
| 1201 | - } | |
| 1202 | - subscribePostitionXml.append("</Query>\r\n"); | |
| 1203 | - | |
| 1204 | - CallIdHeader callIdHeader; | |
| 1205 | - | |
| 1206 | - if (requestOld != null) { | |
| 1207 | - callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId()); | |
| 1208 | - } else { | |
| 1209 | - callIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()); | |
| 1210 | - } | |
| 1211 | - SIPRequest request = (SIPRequest) headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), requestOld, device.getSubscribeCycleForMobilePosition(), "presence",callIdHeader); //Position;id=" + tm.substring(tm.length() - 4)); | |
| 1212 | - | |
| 1213 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, okEvent); | |
| 1214 | - return request; | |
| 1215 | - } | |
| 1216 | - | |
| 1217 | - /** | |
| 1218 | - * 订阅、取消订阅报警信息 | |
| 1219 | - * | |
| 1220 | - * @param device 视频设备 | |
| 1221 | - * @param expires 订阅过期时间(0 = 取消订阅) | |
| 1222 | - * @param startPriority 报警起始级别(可选) | |
| 1223 | - * @param endPriority 报警终止级别(可选) | |
| 1224 | - * @param alarmMethod 报警方式条件(可选) | |
| 1225 | - * @param alarmType 报警类型 | |
| 1226 | - * @param startTime 报警发生起始时间(可选) | |
| 1227 | - * @param endTime 报警发生终止时间(可选) | |
| 1228 | - * @return true = 命令发送成功 | |
| 1229 | - */ | |
| 1230 | - @Override | |
| 1231 | - public void alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String startTime, String endTime) throws InvalidArgumentException, SipException, ParseException { | |
| 1232 | - | |
| 1233 | - StringBuffer cmdXml = new StringBuffer(200); | |
| 1234 | - String charset = device.getCharset(); | |
| 1235 | - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 1236 | - cmdXml.append("<Query>\r\n"); | |
| 1237 | - cmdXml.append("<CmdType>Alarm</CmdType>\r\n"); | |
| 1238 | - cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 1239 | - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 1240 | - if (!ObjectUtils.isEmpty(startPriority)) { | |
| 1241 | - cmdXml.append("<StartAlarmPriority>" + startPriority + "</StartAlarmPriority>\r\n"); | |
| 1242 | - } | |
| 1243 | - if (!ObjectUtils.isEmpty(endPriority)) { | |
| 1244 | - cmdXml.append("<EndAlarmPriority>" + endPriority + "</EndAlarmPriority>\r\n"); | |
| 1245 | - } | |
| 1246 | - if (!ObjectUtils.isEmpty(alarmMethod)) { | |
| 1247 | - cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n"); | |
| 1248 | - } | |
| 1249 | - if (!ObjectUtils.isEmpty(startTime)) { | |
| 1250 | - cmdXml.append("<StartAlarmTime>" + startTime + "</StartAlarmTime>\r\n"); | |
| 1251 | - } | |
| 1252 | - if (!ObjectUtils.isEmpty(endTime)) { | |
| 1253 | - cmdXml.append("<EndAlarmTime>" + endTime + "</EndAlarmTime>\r\n"); | |
| 1254 | - } | |
| 1255 | - cmdXml.append("</Query>\r\n"); | |
| 1256 | - | |
| 1257 | - | |
| 1258 | - | |
| 1259 | - Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), null, expires, "presence",sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 1260 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request); | |
| 1261 | - | |
| 1262 | - } | |
| 1263 | - | |
| 1264 | - @Override | |
| 1265 | - public SIPRequest catalogSubscribe(Device device, SIPRequest requestOld, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 1266 | - | |
| 1267 | - StringBuffer cmdXml = new StringBuffer(200); | |
| 1268 | - String charset = device.getCharset(); | |
| 1269 | - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 1270 | - cmdXml.append("<Query>\r\n"); | |
| 1271 | - cmdXml.append("<CmdType>Catalog</CmdType>\r\n"); | |
| 1272 | - cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 1273 | - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 1274 | - cmdXml.append("</Query>\r\n"); | |
| 1275 | - | |
| 1276 | - CallIdHeader callIdHeader; | |
| 1277 | - | |
| 1278 | - if (requestOld != null) { | |
| 1279 | - callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId()); | |
| 1280 | - } else { | |
| 1281 | - callIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()); | |
| 1282 | - } | |
| 1283 | - | |
| 1284 | - // 有效时间默认为60秒以上 | |
| 1285 | - SIPRequest request = (SIPRequest) headerProvider.createSubscribeRequest(device, cmdXml.toString(), requestOld, device.getSubscribeCycleForCatalog(), "Catalog", | |
| 1286 | - callIdHeader); | |
| 1287 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, okEvent); | |
| 1288 | - return request; | |
| 1289 | - } | |
| 1290 | - | |
| 1291 | - @Override | |
| 1292 | - public void dragZoomCmd(Device device, String channelId, String cmdString) throws InvalidArgumentException, SipException, ParseException { | |
| 1293 | - | |
| 1294 | - StringBuffer dragXml = new StringBuffer(200); | |
| 1295 | - String charset = device.getCharset(); | |
| 1296 | - dragXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 1297 | - dragXml.append("<Control>\r\n"); | |
| 1298 | - dragXml.append("<CmdType>DeviceControl</CmdType>\r\n"); | |
| 1299 | - dragXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 1300 | - if (ObjectUtils.isEmpty(channelId)) { | |
| 1301 | - dragXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 1302 | - } else { | |
| 1303 | - dragXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 1304 | - } | |
| 1305 | - dragXml.append(cmdString); | |
| 1306 | - dragXml.append("</Control>\r\n"); | |
| 1307 | - | |
| 1308 | - Request request = headerProvider.createMessageRequest(device, dragXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 1309 | - logger.debug("拉框信令: " + request.toString()); | |
| 1310 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()),request); | |
| 1311 | - } | |
| 1312 | - | |
| 1313 | - | |
| 1314 | - | |
| 1315 | - | |
| 1316 | - | |
| 1317 | - /** | |
| 1318 | - * 回放暂停 | |
| 1319 | - */ | |
| 1320 | - @Override | |
| 1321 | - public void playPauseCmd(Device device, StreamInfo streamInfo) throws InvalidArgumentException, ParseException, SipException { | |
| 1322 | - StringBuffer content = new StringBuffer(200); | |
| 1323 | - content.append("PAUSE RTSP/1.0\r\n"); | |
| 1324 | - content.append("CSeq: " + getInfoCseq() + "\r\n"); | |
| 1325 | - content.append("PauseTime: now\r\n"); | |
| 1326 | - | |
| 1327 | - playbackControlCmd(device, streamInfo, content.toString(), null, null); | |
| 1328 | - } | |
| 1329 | - | |
| 1330 | - | |
| 1331 | - /** | |
| 1332 | - * 回放恢复 | |
| 1333 | - */ | |
| 1334 | - @Override | |
| 1335 | - public void playResumeCmd(Device device, StreamInfo streamInfo) throws InvalidArgumentException, ParseException, SipException { | |
| 1336 | - StringBuffer content = new StringBuffer(200); | |
| 1337 | - content.append("PLAY RTSP/1.0\r\n"); | |
| 1338 | - content.append("CSeq: " + getInfoCseq() + "\r\n"); | |
| 1339 | - content.append("Range: npt=now-\r\n"); | |
| 1340 | - | |
| 1341 | - playbackControlCmd(device, streamInfo, content.toString(), null, null); | |
| 1342 | - } | |
| 1343 | - | |
| 1344 | - /** | |
| 1345 | - * 回放拖动播放 | |
| 1346 | - */ | |
| 1347 | - @Override | |
| 1348 | - public void playSeekCmd(Device device, StreamInfo streamInfo, long seekTime) throws InvalidArgumentException, ParseException, SipException { | |
| 1349 | - StringBuffer content = new StringBuffer(200); | |
| 1350 | - content.append("PLAY RTSP/1.0\r\n"); | |
| 1351 | - content.append("CSeq: " + getInfoCseq() + "\r\n"); | |
| 1352 | - content.append("Range: npt=" + Math.abs(seekTime) + "-\r\n"); | |
| 1353 | - | |
| 1354 | - playbackControlCmd(device, streamInfo, content.toString(), null, null); | |
| 1355 | - } | |
| 1356 | - | |
| 1357 | - /** | |
| 1358 | - * 回放倍速播放 | |
| 1359 | - */ | |
| 1360 | - @Override | |
| 1361 | - public void playSpeedCmd(Device device, StreamInfo streamInfo, Double speed) throws InvalidArgumentException, ParseException, SipException { | |
| 1362 | - StringBuffer content = new StringBuffer(200); | |
| 1363 | - content.append("PLAY RTSP/1.0\r\n"); | |
| 1364 | - content.append("CSeq: " + getInfoCseq() + "\r\n"); | |
| 1365 | - content.append("Scale: " + String.format("%.6f", speed) + "\r\n"); | |
| 1366 | - | |
| 1367 | - playbackControlCmd(device, streamInfo, content.toString(), null, null); | |
| 1368 | - } | |
| 1369 | - | |
| 1370 | - private int getInfoCseq() { | |
| 1371 | - return (int) ((Math.random() * 9 + 1) * Math.pow(10, 8)); | |
| 1372 | - } | |
| 1373 | - | |
| 1374 | - @Override | |
| 1375 | - public void playbackControlCmd(Device device, StreamInfo streamInfo, String content, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException, InvalidArgumentException, ParseException { | |
| 1376 | - | |
| 1377 | - SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(device.getDeviceId(), streamInfo.getChannelId(), null, streamInfo.getStream()); | |
| 1378 | - if (ssrcTransaction == null) { | |
| 1379 | - logger.info("[回放控制]未找到视频流信息,设备:{}, 流ID: {}", device.getDeviceId(), streamInfo.getStream()); | |
| 1380 | - return; | |
| 1381 | - } | |
| 1382 | - | |
| 1383 | - SIPRequest request = headerProvider.createInfoRequest(device, streamInfo.getChannelId(), content.toString(), ssrcTransaction.getSipTransactionInfo()); | |
| 1384 | - if (request == null) { | |
| 1385 | - logger.info("[回放控制]构建Request信息失败,设备:{}, 流ID: {}", device.getDeviceId(), streamInfo.getStream()); | |
| 1386 | - return; | |
| 1387 | - } | |
| 1388 | - | |
| 1389 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, okEvent); | |
| 1390 | - } | |
| 1391 | - | |
| 1392 | - @Override | |
| 1393 | - public void sendAlarmMessage(Device device, DeviceAlarm deviceAlarm) throws InvalidArgumentException, SipException, ParseException { | |
| 1394 | - if (device == null) { | |
| 1395 | - return; | |
| 1396 | - } | |
| 1397 | - logger.info("[发送报警通知]设备: {}/{}->{},{}", device.getDeviceId(), deviceAlarm.getChannelId(), | |
| 1398 | - deviceAlarm.getLongitude(), deviceAlarm.getLatitude()); | |
| 1399 | - | |
| 1400 | - String characterSet = device.getCharset(); | |
| 1401 | - StringBuffer deviceStatusXml = new StringBuffer(600); | |
| 1402 | - deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n"); | |
| 1403 | - deviceStatusXml.append("<Notify>\r\n"); | |
| 1404 | - deviceStatusXml.append("<CmdType>Alarm</CmdType>\r\n"); | |
| 1405 | - deviceStatusXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 1406 | - deviceStatusXml.append("<DeviceID>" + deviceAlarm.getChannelId() + "</DeviceID>\r\n"); | |
| 1407 | - deviceStatusXml.append("<AlarmPriority>" + deviceAlarm.getAlarmPriority() + "</AlarmPriority>\r\n"); | |
| 1408 | - deviceStatusXml.append("<AlarmMethod>" + deviceAlarm.getAlarmMethod() + "</AlarmMethod>\r\n"); | |
| 1409 | - deviceStatusXml.append("<AlarmTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(deviceAlarm.getAlarmTime()) + "</AlarmTime>\r\n"); | |
| 1410 | - deviceStatusXml.append("<AlarmDescription>" + deviceAlarm.getAlarmDescription() + "</AlarmDescription>\r\n"); | |
| 1411 | - deviceStatusXml.append("<Longitude>" + deviceAlarm.getLongitude() + "</Longitude>\r\n"); | |
| 1412 | - deviceStatusXml.append("<Latitude>" + deviceAlarm.getLatitude() + "</Latitude>\r\n"); | |
| 1413 | - deviceStatusXml.append("<info>\r\n"); | |
| 1414 | - deviceStatusXml.append("<AlarmType>" + deviceAlarm.getAlarmType() + "</AlarmType>\r\n"); | |
| 1415 | - deviceStatusXml.append("</info>\r\n"); | |
| 1416 | - deviceStatusXml.append("</Notify>\r\n"); | |
| 1417 | - | |
| 1418 | - | |
| 1419 | - Request request = headerProvider.createMessageRequest(device, deviceStatusXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 1420 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()),request); | |
| 1421 | - | |
| 1422 | - | |
| 1423 | - } | |
| 1424 | -} | |
| 1 | +package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl; | |
| 2 | + | |
| 3 | +import com.genersoft.iot.vmp.common.InviteSessionType; | |
| 4 | +import com.genersoft.iot.vmp.common.StreamInfo; | |
| 5 | +import com.genersoft.iot.vmp.conf.SipConfig; | |
| 6 | +import com.genersoft.iot.vmp.conf.UserSetting; | |
| 7 | +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; | |
| 8 | +import com.genersoft.iot.vmp.gb28181.SipLayer; | |
| 9 | +import com.genersoft.iot.vmp.gb28181.bean.*; | |
| 10 | +import com.genersoft.iot.vmp.gb28181.bean.Device; | |
| 11 | +import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; | |
| 12 | +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; | |
| 13 | +import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction; | |
| 14 | +import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | |
| 15 | +import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | |
| 16 | +import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; | |
| 17 | +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; | |
| 18 | +import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider; | |
| 19 | +import com.genersoft.iot.vmp.gb28181.utils.NumericUtil; | |
| 20 | +import com.genersoft.iot.vmp.gb28181.utils.SipUtils; | |
| 21 | +import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; | |
| 22 | +import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; | |
| 23 | +import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; | |
| 24 | +import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; | |
| 25 | +import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamPush; | |
| 26 | +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | |
| 27 | +import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam; | |
| 28 | +import com.genersoft.iot.vmp.service.IMediaServerService; | |
| 29 | +import com.genersoft.iot.vmp.service.bean.SSRCInfo; | |
| 30 | +import com.genersoft.iot.vmp.utils.DateUtil; | |
| 31 | +import gov.nist.javax.sip.message.SIPRequest; | |
| 32 | +import gov.nist.javax.sip.message.SIPResponse; | |
| 33 | +import org.slf4j.Logger; | |
| 34 | +import org.slf4j.LoggerFactory; | |
| 35 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 36 | +import org.springframework.context.annotation.DependsOn; | |
| 37 | +import org.springframework.stereotype.Component; | |
| 38 | +import org.springframework.util.ObjectUtils; | |
| 39 | + | |
| 40 | +import javax.sip.InvalidArgumentException; | |
| 41 | +import javax.sip.ResponseEvent; | |
| 42 | +import javax.sip.SipException; | |
| 43 | +import javax.sip.SipFactory; | |
| 44 | +import javax.sip.header.CallIdHeader; | |
| 45 | +import javax.sip.message.Request; | |
| 46 | +import java.text.ParseException; | |
| 47 | +import java.util.ArrayList; | |
| 48 | +import java.util.List; | |
| 49 | + | |
| 50 | +/** | |
| 51 | + * @description:设备能力接口,用于定义设备的控制、查询能力 | |
| 52 | + * @author: swwheihei | |
| 53 | + * @date: 2020年5月3日 下午9:22:48 | |
| 54 | + */ | |
| 55 | +@Component | |
| 56 | +@DependsOn("sipLayer") | |
| 57 | +public class SIPCommander implements ISIPCommander { | |
| 58 | + | |
| 59 | + private final Logger logger = LoggerFactory.getLogger(SIPCommander.class); | |
| 60 | + | |
| 61 | + @Autowired | |
| 62 | + private SipConfig sipConfig; | |
| 63 | + | |
| 64 | + @Autowired | |
| 65 | + private SipLayer sipLayer; | |
| 66 | + | |
| 67 | + @Autowired | |
| 68 | + private SIPSender sipSender; | |
| 69 | + | |
| 70 | + @Autowired | |
| 71 | + private SIPRequestHeaderProvider headerProvider; | |
| 72 | + | |
| 73 | + @Autowired | |
| 74 | + private VideoStreamSessionManager streamSession; | |
| 75 | + | |
| 76 | + @Autowired | |
| 77 | + private UserSetting userSetting; | |
| 78 | + | |
| 79 | + @Autowired | |
| 80 | + private ZlmHttpHookSubscribe subscribe; | |
| 81 | + | |
| 82 | + @Autowired | |
| 83 | + private IMediaServerService mediaServerService; | |
| 84 | + | |
| 85 | + @Autowired | |
| 86 | + private ZLMServerFactory zlmServerFactory; | |
| 87 | + | |
| 88 | + | |
| 89 | + /** | |
| 90 | + * 云台方向放控制,使用配置文件中的默认镜头移动速度 | |
| 91 | + * | |
| 92 | + * @param device 控制设备 | |
| 93 | + * @param channelId 预览通道 | |
| 94 | + * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 | |
| 95 | + * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 | |
| 96 | + */ | |
| 97 | + @Override | |
| 98 | + public void ptzdirectCmd(Device device, String channelId, int leftRight, int upDown) throws InvalidArgumentException, ParseException, SipException { | |
| 99 | + ptzCmd(device, channelId, leftRight, upDown, 0, sipConfig.getPtzSpeed(), 0); | |
| 100 | + } | |
| 101 | + | |
| 102 | + /** | |
| 103 | + * 云台方向放控制 | |
| 104 | + * | |
| 105 | + * @param device 控制设备 | |
| 106 | + * @param channelId 预览通道 | |
| 107 | + * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 | |
| 108 | + * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 | |
| 109 | + * @param moveSpeed 镜头移动速度 | |
| 110 | + */ | |
| 111 | + @Override | |
| 112 | + public void ptzdirectCmd(Device device, String channelId, int leftRight, int upDown, int moveSpeed) throws InvalidArgumentException, ParseException, SipException { | |
| 113 | + ptzCmd(device, channelId, leftRight, upDown, 0, moveSpeed, 0); | |
| 114 | + } | |
| 115 | + | |
| 116 | + /** | |
| 117 | + * 云台缩放控制,使用配置文件中的默认镜头缩放速度 | |
| 118 | + * | |
| 119 | + * @param device 控制设备 | |
| 120 | + * @param channelId 预览通道 | |
| 121 | + * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 | |
| 122 | + */ | |
| 123 | + @Override | |
| 124 | + public void ptzZoomCmd(Device device, String channelId, int inOut) throws InvalidArgumentException, ParseException, SipException { | |
| 125 | + ptzCmd(device, channelId, 0, 0, inOut, 0, sipConfig.getPtzSpeed()); | |
| 126 | + } | |
| 127 | + | |
| 128 | + /** | |
| 129 | + * 云台缩放控制 | |
| 130 | + * | |
| 131 | + * @param device 控制设备 | |
| 132 | + * @param channelId 预览通道 | |
| 133 | + * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 | |
| 134 | + * @param zoomSpeed 镜头缩放速度 | |
| 135 | + */ | |
| 136 | + @Override | |
| 137 | + public void ptzZoomCmd(Device device, String channelId, int inOut, int zoomSpeed) throws InvalidArgumentException, ParseException, SipException { | |
| 138 | + ptzCmd(device, channelId, 0, 0, inOut, 0, zoomSpeed); | |
| 139 | + } | |
| 140 | + | |
| 141 | + /** | |
| 142 | + * 云台指令码计算 | |
| 143 | + * | |
| 144 | + * @param cmdCode 指令码 | |
| 145 | + * @param parameter1 数据1 | |
| 146 | + * @param parameter2 数据2 | |
| 147 | + * @param combineCode2 组合码2 | |
| 148 | + */ | |
| 149 | + public static String frontEndCmdString(int cmdCode, int parameter1, int parameter2, int combineCode2) { | |
| 150 | + StringBuilder builder = new StringBuilder("A50F01"); | |
| 151 | + String strTmp; | |
| 152 | + strTmp = String.format("%02X", cmdCode); | |
| 153 | + builder.append(strTmp, 0, 2); | |
| 154 | + strTmp = String.format("%02X", parameter1); | |
| 155 | + builder.append(strTmp, 0, 2); | |
| 156 | + strTmp = String.format("%02X", parameter2); | |
| 157 | + builder.append(strTmp, 0, 2); | |
| 158 | + //优化zoom变倍速率 | |
| 159 | + if ((combineCode2 > 0) && (combineCode2 <16)) | |
| 160 | + { | |
| 161 | + combineCode2 = 16; | |
| 162 | + } | |
| 163 | + strTmp = String.format("%X", combineCode2); | |
| 164 | + builder.append(strTmp, 0, 1).append("0"); | |
| 165 | + //计算校验码 | |
| 166 | + int checkCode = (0XA5 + 0X0F + 0X01 + cmdCode + parameter1 + parameter2 + (combineCode2 & 0XF0)) % 0X100; | |
| 167 | + strTmp = String.format("%02X", checkCode); | |
| 168 | + builder.append(strTmp, 0, 2); | |
| 169 | + return builder.toString(); | |
| 170 | + } | |
| 171 | + | |
| 172 | + /** | |
| 173 | + * 云台控制,支持方向与缩放控制 | |
| 174 | + * | |
| 175 | + * @param device 控制设备 | |
| 176 | + * @param channelId 预览通道 | |
| 177 | + * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 | |
| 178 | + * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 | |
| 179 | + * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 | |
| 180 | + * @param moveSpeed 镜头移动速度 | |
| 181 | + * @param zoomSpeed 镜头缩放速度 | |
| 182 | + */ | |
| 183 | + @Override | |
| 184 | + public void ptzCmd(Device device, String channelId, int leftRight, int upDown, int inOut, int moveSpeed, | |
| 185 | + int zoomSpeed) throws InvalidArgumentException, SipException, ParseException { | |
| 186 | + String cmdStr = SipUtils.cmdString(leftRight, upDown, inOut, moveSpeed, zoomSpeed); | |
| 187 | + StringBuilder ptzXml = new StringBuilder(200); | |
| 188 | + String charset = device.getCharset(); | |
| 189 | + ptzXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 190 | + ptzXml.append("<Control>\r\n"); | |
| 191 | + ptzXml.append("<CmdType>DeviceControl</CmdType>\r\n"); | |
| 192 | + ptzXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 193 | + ptzXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 194 | + ptzXml.append("<PTZCmd>" + cmdStr + "</PTZCmd>\r\n"); | |
| 195 | + ptzXml.append("<Info>\r\n"); | |
| 196 | + ptzXml.append("<ControlPriority>5</ControlPriority>\r\n"); | |
| 197 | + ptzXml.append("</Info>\r\n"); | |
| 198 | + ptzXml.append("</Control>\r\n"); | |
| 199 | + | |
| 200 | + Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 201 | + | |
| 202 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()),request); | |
| 203 | + } | |
| 204 | + | |
| 205 | + /** | |
| 206 | + * 前端控制,包括PTZ指令、FI指令、预置位指令、巡航指令、扫描指令和辅助开关指令 | |
| 207 | + * | |
| 208 | + * @param device 控制设备 | |
| 209 | + * @param channelId 预览通道 | |
| 210 | + * @param cmdCode 指令码 | |
| 211 | + * @param parameter1 数据1 | |
| 212 | + * @param parameter2 数据2 | |
| 213 | + * @param combineCode2 组合码2 | |
| 214 | + */ | |
| 215 | + @Override | |
| 216 | + public void frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2) throws SipException, InvalidArgumentException, ParseException { | |
| 217 | + | |
| 218 | + String cmdStr = frontEndCmdString(cmdCode, parameter1, parameter2, combineCode2); | |
| 219 | + StringBuffer ptzXml = new StringBuffer(200); | |
| 220 | + String charset = device.getCharset(); | |
| 221 | + ptzXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 222 | + ptzXml.append("<Control>\r\n"); | |
| 223 | + ptzXml.append("<CmdType>DeviceControl</CmdType>\r\n"); | |
| 224 | + ptzXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 225 | + ptzXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 226 | + ptzXml.append("<PTZCmd>" + cmdStr + "</PTZCmd>\r\n"); | |
| 227 | + ptzXml.append("<Info>\r\n"); | |
| 228 | + ptzXml.append("<ControlPriority>5</ControlPriority>\r\n"); | |
| 229 | + ptzXml.append("</Info>\r\n"); | |
| 230 | + ptzXml.append("</Control>\r\n"); | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + SIPRequest request = (SIPRequest) headerProvider.createMessageRequest(device, ptzXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 236 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()),request); | |
| 237 | + | |
| 238 | + } | |
| 239 | + | |
| 240 | + /** | |
| 241 | + * 前端控制指令(用于转发上级指令) | |
| 242 | + * | |
| 243 | + * @param device 控制设备 | |
| 244 | + * @param channelId 预览通道 | |
| 245 | + * @param cmdString 前端控制指令串 | |
| 246 | + */ | |
| 247 | + @Override | |
| 248 | + public void fronEndCmd(Device device, String channelId, String cmdString, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 249 | + | |
| 250 | + StringBuffer ptzXml = new StringBuffer(200); | |
| 251 | + String charset = device.getCharset(); | |
| 252 | + ptzXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 253 | + ptzXml.append("<Control>\r\n"); | |
| 254 | + ptzXml.append("<CmdType>DeviceControl</CmdType>\r\n"); | |
| 255 | + ptzXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 256 | + ptzXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 257 | + ptzXml.append("<PTZCmd>" + cmdString + "</PTZCmd>\r\n"); | |
| 258 | + ptzXml.append("<Info>\r\n"); | |
| 259 | + ptzXml.append("<ControlPriority>5</ControlPriority>\r\n"); | |
| 260 | + ptzXml.append("</Info>\r\n"); | |
| 261 | + ptzXml.append("</Control>\r\n"); | |
| 262 | + | |
| 263 | + | |
| 264 | + Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 265 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()),request, errorEvent, okEvent); | |
| 266 | + | |
| 267 | + } | |
| 268 | + | |
| 269 | + /** | |
| 270 | + * 请求预览视频流 | |
| 271 | + * | |
| 272 | + * @param device 视频设备 | |
| 273 | + * @param channel 预览通道 | |
| 274 | + * @param event hook订阅 | |
| 275 | + * @param errorEvent sip错误订阅 | |
| 276 | + */ | |
| 277 | + @Override | |
| 278 | + public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel, | |
| 279 | + ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 280 | + String stream = ssrcInfo.getStream(); | |
| 281 | + | |
| 282 | + if (device == null) { | |
| 283 | + return; | |
| 284 | + } | |
| 285 | + | |
| 286 | + logger.info("{} 分配的ZLM为: {} [{}:{}]", stream, mediaServerItem.getId(), mediaServerItem.getSdpIp(), ssrcInfo.getPort()); | |
| 287 | + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId()); | |
| 288 | + subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, HookParam hookParam) -> { | |
| 289 | + if (event != null) { | |
| 290 | + event.response(mediaServerItemInUse, hookParam); | |
| 291 | + subscribe.removeSubscribe(hookSubscribe); | |
| 292 | + } | |
| 293 | + }); | |
| 294 | + String sdpIp; | |
| 295 | + if (!ObjectUtils.isEmpty(device.getSdpIp())) { | |
| 296 | + sdpIp = device.getSdpIp(); | |
| 297 | + }else { | |
| 298 | + sdpIp = mediaServerItem.getSdpIp(); | |
| 299 | + } | |
| 300 | + StringBuffer content = new StringBuffer(200); | |
| 301 | + content.append("v=0\r\n"); | |
| 302 | + content.append("o=" + channel.getChannelId() + " 0 0 IN IP4 " + sdpIp + "\r\n"); | |
| 303 | + content.append("s=Play\r\n"); | |
| 304 | + content.append("c=IN IP4 " + sdpIp + "\r\n"); | |
| 305 | + content.append("t=0 0\r\n"); | |
| 306 | + | |
| 307 | + if (userSetting.isSeniorSdp()) { | |
| 308 | + if ("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) { | |
| 309 | + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 126 125 99 34 98 97\r\n"); | |
| 310 | + } else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) { | |
| 311 | + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 126 125 99 34 98 97\r\n"); | |
| 312 | + } else if ("UDP".equalsIgnoreCase(device.getStreamMode())) { | |
| 313 | + content.append("m=video " + ssrcInfo.getPort() + " RTP/AVP 96 126 125 99 34 98 97\r\n"); | |
| 314 | + } | |
| 315 | + content.append("a=recvonly\r\n"); | |
| 316 | + content.append("a=rtpmap:96 PS/90000\r\n"); | |
| 317 | + content.append("a=fmtp:126 profile-level-id=42e01e\r\n"); | |
| 318 | + content.append("a=rtpmap:126 H264/90000\r\n"); | |
| 319 | + content.append("a=rtpmap:125 H264S/90000\r\n"); | |
| 320 | + content.append("a=fmtp:125 profile-level-id=42e01e\r\n"); | |
| 321 | + content.append("a=rtpmap:99 H265/90000\r\n"); | |
| 322 | + content.append("a=rtpmap:98 H264/90000\r\n"); | |
| 323 | + content.append("a=rtpmap:97 MPEG4/90000\r\n"); | |
| 324 | + if ("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp被动模式 | |
| 325 | + content.append("a=setup:passive\r\n"); | |
| 326 | + content.append("a=connection:new\r\n"); | |
| 327 | + } else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp主动模式 | |
| 328 | + content.append("a=setup:active\r\n"); | |
| 329 | + content.append("a=connection:new\r\n"); | |
| 330 | + } | |
| 331 | + } else { | |
| 332 | + if ("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) { | |
| 333 | + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 97 98 99\r\n"); | |
| 334 | + } else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) { | |
| 335 | + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 97 98 99\r\n"); | |
| 336 | + } else if ("UDP".equalsIgnoreCase(device.getStreamMode())) { | |
| 337 | + content.append("m=video " + ssrcInfo.getPort() + " RTP/AVP 96 97 98 99\r\n"); | |
| 338 | + } | |
| 339 | + content.append("a=recvonly\r\n"); | |
| 340 | + content.append("a=rtpmap:96 PS/90000\r\n"); | |
| 341 | + content.append("a=rtpmap:98 H264/90000\r\n"); | |
| 342 | + content.append("a=rtpmap:97 MPEG4/90000\r\n"); | |
| 343 | + content.append("a=rtpmap:99 H265/90000\r\n"); | |
| 344 | + if ("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp被动模式 | |
| 345 | + content.append("a=setup:passive\r\n"); | |
| 346 | + content.append("a=connection:new\r\n"); | |
| 347 | + } else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp主动模式 | |
| 348 | + content.append("a=setup:active\r\n"); | |
| 349 | + content.append("a=connection:new\r\n"); | |
| 350 | + } | |
| 351 | + } | |
| 352 | + | |
| 353 | + if (!ObjectUtils.isEmpty(channel.getStreamIdentification())) { | |
| 354 | + content.append("a=" + channel.getStreamIdentification() + "\r\n"); | |
| 355 | + } | |
| 356 | + | |
| 357 | + content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc | |
| 358 | + // f字段:f= v/编码格式/分辨率/帧率/码率类型/码率大小a/编码格式/码率大小/采样率 | |
| 359 | +// content.append("f=v/2/5/25/1/4000a/1/8/1" + "\r\n"); // 未发现支持此特性的设备 | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + Request request = headerProvider.createInviteRequest(device, channel.getChannelId(), content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 364 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> { | |
| 365 | + streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream()); | |
| 366 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | |
| 367 | + errorEvent.response(e); | |
| 368 | + }), e -> { | |
| 369 | + ResponseEvent responseEvent = (ResponseEvent) e.event; | |
| 370 | + SIPResponse response = (SIPResponse) responseEvent.getResponse(); | |
| 371 | + String callId = response.getCallIdHeader().getCallId(); | |
| 372 | + streamSession.put(device.getDeviceId(), channel.getChannelId(), callId, stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response, | |
| 373 | + InviteSessionType.PLAY); | |
| 374 | + okEvent.response(e); | |
| 375 | + }); | |
| 376 | + } | |
| 377 | + | |
| 378 | + /** | |
| 379 | + * 请求回放视频流 | |
| 380 | + * | |
| 381 | + * @param device 视频设备 | |
| 382 | + * @param channelId 预览通道 | |
| 383 | + * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss | |
| 384 | + * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss | |
| 385 | + */ | |
| 386 | + @Override | |
| 387 | + public void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, | |
| 388 | + String startTime, String endTime, ZlmHttpHookSubscribe.Event hookEvent, | |
| 389 | + SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 390 | + | |
| 391 | + | |
| 392 | + logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getSdpIp(), ssrcInfo.getPort()); | |
| 393 | + String sdpIp; | |
| 394 | + if (!ObjectUtils.isEmpty(device.getSdpIp())) { | |
| 395 | + sdpIp = device.getSdpIp(); | |
| 396 | + }else { | |
| 397 | + sdpIp = mediaServerItem.getSdpIp(); | |
| 398 | + } | |
| 399 | + StringBuffer content = new StringBuffer(200); | |
| 400 | + content.append("v=0\r\n"); | |
| 401 | + content.append("o=" + channelId + " 0 0 IN IP4 " + sdpIp + "\r\n"); | |
| 402 | + content.append("s=Playback\r\n"); | |
| 403 | + content.append("u=" + channelId + ":0\r\n"); | |
| 404 | + content.append("c=IN IP4 " + sdpIp + "\r\n"); | |
| 405 | + content.append("t=" + DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime) + " " | |
| 406 | + + DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) + "\r\n"); | |
| 407 | + | |
| 408 | + String streamMode = device.getStreamMode(); | |
| 409 | + | |
| 410 | + if (userSetting.isSeniorSdp()) { | |
| 411 | + if ("TCP-PASSIVE".equalsIgnoreCase(streamMode)) { | |
| 412 | + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 126 125 99 34 98 97\r\n"); | |
| 413 | + } else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) { | |
| 414 | + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 126 125 99 34 98 97\r\n"); | |
| 415 | + } else if ("UDP".equalsIgnoreCase(streamMode)) { | |
| 416 | + content.append("m=video " + ssrcInfo.getPort() + " RTP/AVP 96 126 125 99 34 98 97\r\n"); | |
| 417 | + } | |
| 418 | + content.append("a=recvonly\r\n"); | |
| 419 | + content.append("a=rtpmap:96 PS/90000\r\n"); | |
| 420 | + content.append("a=fmtp:126 profile-level-id=42e01e\r\n"); | |
| 421 | + content.append("a=rtpmap:126 H264/90000\r\n"); | |
| 422 | + content.append("a=rtpmap:125 H264S/90000\r\n"); | |
| 423 | + content.append("a=fmtp:125 profile-level-id=42e01e\r\n"); | |
| 424 | + content.append("a=rtpmap:99 H265/90000\r\n"); | |
| 425 | + content.append("a=rtpmap:98 H264/90000\r\n"); | |
| 426 | + content.append("a=rtpmap:97 MPEG4/90000\r\n"); | |
| 427 | + if ("TCP-PASSIVE".equalsIgnoreCase(streamMode)) { // tcp被动模式 | |
| 428 | + content.append("a=setup:passive\r\n"); | |
| 429 | + content.append("a=connection:new\r\n"); | |
| 430 | + } else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) { // tcp主动模式 | |
| 431 | + content.append("a=setup:active\r\n"); | |
| 432 | + content.append("a=connection:new\r\n"); | |
| 433 | + } | |
| 434 | + } else { | |
| 435 | + if ("TCP-PASSIVE".equalsIgnoreCase(streamMode)) { | |
| 436 | + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 97 98 99\r\n"); | |
| 437 | + } else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) { | |
| 438 | + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 97 98 99\r\n"); | |
| 439 | + } else if ("UDP".equalsIgnoreCase(streamMode)) { | |
| 440 | + content.append("m=video " + ssrcInfo.getPort() + " RTP/AVP 96 97 98 99\r\n"); | |
| 441 | + } | |
| 442 | + content.append("a=recvonly\r\n"); | |
| 443 | + content.append("a=rtpmap:96 PS/90000\r\n"); | |
| 444 | + content.append("a=rtpmap:97 MPEG4/90000\r\n"); | |
| 445 | + content.append("a=rtpmap:98 H264/90000\r\n"); | |
| 446 | + content.append("a=rtpmap:99 H265/90000\r\n"); | |
| 447 | + if ("TCP-PASSIVE".equalsIgnoreCase(streamMode)) { | |
| 448 | + // tcp被动模式 | |
| 449 | + content.append("a=setup:passive\r\n"); | |
| 450 | + content.append("a=connection:new\r\n"); | |
| 451 | + } else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) { | |
| 452 | + // tcp主动模式 | |
| 453 | + content.append("a=setup:active\r\n"); | |
| 454 | + content.append("a=connection:new\r\n"); | |
| 455 | + } | |
| 456 | + } | |
| 457 | + | |
| 458 | + //ssrc | |
| 459 | + content.append("y=" + ssrcInfo.getSsrc() + "\r\n"); | |
| 460 | + | |
| 461 | + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId()); | |
| 462 | + // 添加订阅 | |
| 463 | + subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, HookParam hookParam) -> { | |
| 464 | + if (hookEvent != null) { | |
| 465 | + hookEvent.response(mediaServerItemInUse, hookParam); | |
| 466 | + } | |
| 467 | + subscribe.removeSubscribe(hookSubscribe); | |
| 468 | + }); | |
| 469 | + Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()), ssrcInfo.getSsrc()); | |
| 470 | + | |
| 471 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, event -> { | |
| 472 | + ResponseEvent responseEvent = (ResponseEvent) event.event; | |
| 473 | + SIPResponse response = (SIPResponse) responseEvent.getResponse(); | |
| 474 | + streamSession.put(device.getDeviceId(), channelId,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response, InviteSessionType.PLAYBACK); | |
| 475 | + okEvent.response(event); | |
| 476 | + }); | |
| 477 | + } | |
| 478 | + | |
| 479 | + /** | |
| 480 | + * 请求历史媒体下载 | |
| 481 | + * | |
| 482 | + * @param device 视频设备 | |
| 483 | + * @param channelId 预览通道 | |
| 484 | + * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss | |
| 485 | + * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss | |
| 486 | + * @param downloadSpeed 下载倍速参数 | |
| 487 | + */ | |
| 488 | + @Override | |
| 489 | + public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, | |
| 490 | + String startTime, String endTime, int downloadSpeed, | |
| 491 | + ZlmHttpHookSubscribe.Event hookEvent, | |
| 492 | + SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 493 | + | |
| 494 | + logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getSdpIp(), ssrcInfo.getPort()); | |
| 495 | + String sdpIp; | |
| 496 | + if (!ObjectUtils.isEmpty(device.getSdpIp())) { | |
| 497 | + sdpIp = device.getSdpIp(); | |
| 498 | + }else { | |
| 499 | + sdpIp = mediaServerItem.getSdpIp(); | |
| 500 | + } | |
| 501 | + StringBuffer content = new StringBuffer(200); | |
| 502 | + content.append("v=0\r\n"); | |
| 503 | + content.append("o=" + channelId + " 0 0 IN IP4 " + sdpIp + "\r\n"); | |
| 504 | + content.append("s=Download\r\n"); | |
| 505 | + content.append("u=" + channelId + ":0\r\n"); | |
| 506 | + content.append("c=IN IP4 " + sdpIp + "\r\n"); | |
| 507 | + content.append("t=" + DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime) + " " | |
| 508 | + + DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) + "\r\n"); | |
| 509 | + | |
| 510 | + String streamMode = device.getStreamMode().toUpperCase(); | |
| 511 | + | |
| 512 | + if (userSetting.isSeniorSdp()) { | |
| 513 | + if ("TCP-PASSIVE".equals(streamMode)) { | |
| 514 | + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 126 125 99 34 98 97\r\n"); | |
| 515 | + } else if ("TCP-ACTIVE".equals(streamMode)) { | |
| 516 | + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 126 125 99 34 98 97\r\n"); | |
| 517 | + } else if ("UDP".equals(streamMode)) { | |
| 518 | + content.append("m=video " + ssrcInfo.getPort() + " RTP/AVP 96 126 125 99 34 98 97\r\n"); | |
| 519 | + } | |
| 520 | + content.append("a=recvonly\r\n"); | |
| 521 | + content.append("a=rtpmap:96 PS/90000\r\n"); | |
| 522 | + content.append("a=fmtp:126 profile-level-id=42e01e\r\n"); | |
| 523 | + content.append("a=rtpmap:126 H264/90000\r\n"); | |
| 524 | + content.append("a=rtpmap:125 H264S/90000\r\n"); | |
| 525 | + content.append("a=fmtp:125 profile-level-id=42e01e\r\n"); | |
| 526 | + content.append("a=rtpmap:99 MP4V-ES/90000\r\n"); | |
| 527 | + content.append("a=fmtp:99 profile-level-id=3\r\n"); | |
| 528 | + content.append("a=rtpmap:98 H264/90000\r\n"); | |
| 529 | + content.append("a=rtpmap:97 MPEG4/90000\r\n"); | |
| 530 | + if ("TCP-PASSIVE".equals(streamMode)) { // tcp被动模式 | |
| 531 | + content.append("a=setup:passive\r\n"); | |
| 532 | + content.append("a=connection:new\r\n"); | |
| 533 | + } else if ("TCP-ACTIVE".equals(streamMode)) { // tcp主动模式 | |
| 534 | + content.append("a=setup:active\r\n"); | |
| 535 | + content.append("a=connection:new\r\n"); | |
| 536 | + } | |
| 537 | + } else { | |
| 538 | + if ("TCP-PASSIVE".equals(streamMode)) { | |
| 539 | + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 97 98 99\r\n"); | |
| 540 | + } else if ("TCP-ACTIVE".equals(streamMode)) { | |
| 541 | + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 97 98 99\r\n"); | |
| 542 | + } else if ("UDP".equals(streamMode)) { | |
| 543 | + content.append("m=video " + ssrcInfo.getPort() + " RTP/AVP 96 97 98 99\r\n"); | |
| 544 | + } | |
| 545 | + content.append("a=recvonly\r\n"); | |
| 546 | + content.append("a=rtpmap:96 PS/90000\r\n"); | |
| 547 | + content.append("a=rtpmap:97 MPEG4/90000\r\n"); | |
| 548 | + content.append("a=rtpmap:98 H264/90000\r\n"); | |
| 549 | + content.append("a=rtpmap:99 H265/90000\r\n"); | |
| 550 | + if ("TCP-PASSIVE".equals(streamMode)) { // tcp被动模式 | |
| 551 | + content.append("a=setup:passive\r\n"); | |
| 552 | + content.append("a=connection:new\r\n"); | |
| 553 | + } else if ("TCP-ACTIVE".equals(streamMode)) { // tcp主动模式 | |
| 554 | + content.append("a=setup:active\r\n"); | |
| 555 | + content.append("a=connection:new\r\n"); | |
| 556 | + } | |
| 557 | + } | |
| 558 | + content.append("a=downloadspeed:" + downloadSpeed + "\r\n"); | |
| 559 | + | |
| 560 | + content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc | |
| 561 | + logger.debug("此时请求下载信令的ssrc===>{}",ssrcInfo.getSsrc()); | |
| 562 | + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId()); | |
| 563 | + // 添加订阅 | |
| 564 | + CallIdHeader newCallIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()), device.getTransport()); | |
| 565 | + String callId= newCallIdHeader.getCallId(); | |
| 566 | + subscribe.addSubscribe(hookSubscribe, (mediaServerItemInUse, hookParam) -> { | |
| 567 | + logger.debug("sipc 添加订阅===callId {}",callId); | |
| 568 | + hookEvent.response(mediaServerItemInUse, hookParam); | |
| 569 | + subscribe.removeSubscribe(hookSubscribe); | |
| 570 | + hookSubscribe.getContent().put("regist", false); | |
| 571 | + hookSubscribe.getContent().put("schema", "rtsp"); | |
| 572 | + // 添加流注销的订阅,注销了后向设备发送bye | |
| 573 | + subscribe.addSubscribe(hookSubscribe, | |
| 574 | + (mediaServerItemForEnd, hookParam1) -> { | |
| 575 | + logger.info("[录像]下载结束, 发送BYE"); | |
| 576 | + try { | |
| 577 | + streamByeCmd(device, channelId, ssrcInfo.getStream(), callId); | |
| 578 | + } catch (InvalidArgumentException | ParseException | SipException | | |
| 579 | + SsrcTransactionNotFoundException e) { | |
| 580 | + logger.error("[录像]下载结束, 发送BYE失败 {}", e.getMessage()); | |
| 581 | + } | |
| 582 | + }); | |
| 583 | + }); | |
| 584 | + | |
| 585 | + Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,newCallIdHeader, ssrcInfo.getSsrc()); | |
| 586 | + | |
| 587 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, event -> { | |
| 588 | + ResponseEvent responseEvent = (ResponseEvent) event.event; | |
| 589 | + SIPResponse response = (SIPResponse) responseEvent.getResponse(); | |
| 590 | + String contentString =new String(response.getRawContent()); | |
| 591 | + String ssrc = SipUtils.getSsrcFromSdp(contentString); | |
| 592 | + streamSession.put(device.getDeviceId(), channelId, response.getCallIdHeader().getCallId(), ssrcInfo.getStream(), ssrc, mediaServerItem.getId(), response, InviteSessionType.DOWNLOAD); | |
| 593 | + okEvent.response(event); | |
| 594 | + }); | |
| 595 | + } | |
| 596 | + | |
| 597 | + @Override | |
| 598 | + public void talkStreamCmd(MediaServerItem mediaServerItem, SendRtpItem sendRtpItem, Device device, String channelId, String callId, ZlmHttpHookSubscribe.Event event, ZlmHttpHookSubscribe.Event eventForPush, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 599 | + | |
| 600 | + String stream = sendRtpItem.getStream(); | |
| 601 | + | |
| 602 | + if (device == null) { | |
| 603 | + return; | |
| 604 | + } | |
| 605 | + if (!mediaServerItem.isRtpEnable()) { | |
| 606 | + // 单端口暂不支持语音喊话 | |
| 607 | + logger.info("[语音喊话] 单端口暂不支持此操作"); | |
| 608 | + return; | |
| 609 | + } | |
| 610 | + | |
| 611 | + logger.info("[语音喊话] {} 分配的ZLM为: {} [{}:{}]", stream, mediaServerItem.getId(), mediaServerItem.getIp(), sendRtpItem.getPort()); | |
| 612 | + HookSubscribeForStreamChange hookSubscribeForStreamChange = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId()); | |
| 613 | + subscribe.addSubscribe(hookSubscribeForStreamChange, (mediaServerItemInUse, hookParam) -> { | |
| 614 | + if (event != null) { | |
| 615 | + event.response(mediaServerItemInUse, hookParam); | |
| 616 | + subscribe.removeSubscribe(hookSubscribeForStreamChange); | |
| 617 | + } | |
| 618 | + }); | |
| 619 | + | |
| 620 | + CallIdHeader callIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()), device.getTransport()); | |
| 621 | + callIdHeader.setCallId(callId); | |
| 622 | + HookSubscribeForStreamPush hookSubscribeForStreamPush = HookSubscribeFactory.on_publish("rtp", stream, null, mediaServerItem.getId()); | |
| 623 | + subscribe.addSubscribe(hookSubscribeForStreamPush, (mediaServerItemInUse, hookParam) -> { | |
| 624 | + if (eventForPush != null) { | |
| 625 | + eventForPush.response(mediaServerItemInUse, hookParam); | |
| 626 | + } | |
| 627 | + }); | |
| 628 | + // | |
| 629 | + StringBuffer content = new StringBuffer(200); | |
| 630 | + content.append("v=0\r\n"); | |
| 631 | + content.append("o=" + channelId + " 0 0 IN IP4 " + mediaServerItem.getSdpIp() + "\r\n"); | |
| 632 | + content.append("s=Talk\r\n"); | |
| 633 | + content.append("c=IN IP4 " + mediaServerItem.getSdpIp() + "\r\n"); | |
| 634 | + content.append("t=0 0\r\n"); | |
| 635 | + | |
| 636 | + content.append("m=audio " + sendRtpItem.getPort() + " TCP/RTP/AVP 8\r\n"); | |
| 637 | + content.append("a=setup:passive\r\n"); | |
| 638 | + content.append("a=connection:new\r\n"); | |
| 639 | + content.append("a=sendrecv\r\n"); | |
| 640 | + content.append("a=rtpmap:8 PCMA/8000\r\n"); | |
| 641 | + | |
| 642 | + content.append("y=" + sendRtpItem.getSsrc() + "\r\n");//ssrc | |
| 643 | + // f字段:f= v/编码格式/分辨率/帧率/码率类型/码率大小a/编码格式/码率大小/采样率 | |
| 644 | + content.append("f=v/////a/1/8/1" + "\r\n"); | |
| 645 | + | |
| 646 | + Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), | |
| 647 | + SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, sendRtpItem.getSsrc(), callIdHeader); | |
| 648 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> { | |
| 649 | + streamSession.remove(device.getDeviceId(), channelId, sendRtpItem.getStream()); | |
| 650 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc()); | |
| 651 | + errorEvent.response(e); | |
| 652 | + }), e -> { | |
| 653 | + // 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值 | |
| 654 | + ResponseEvent responseEvent = (ResponseEvent) e.event; | |
| 655 | + SIPResponse response = (SIPResponse) responseEvent.getResponse(); | |
| 656 | + streamSession.put(device.getDeviceId(), channelId, "talk", stream, sendRtpItem.getSsrc(), mediaServerItem.getId(), response, InviteSessionType.TALK); | |
| 657 | + okEvent.response(e); | |
| 658 | + }); | |
| 659 | + } | |
| 660 | + | |
| 661 | + /** | |
| 662 | + * 视频流停止, 不使用回调 | |
| 663 | + */ | |
| 664 | + @Override | |
| 665 | + public void streamByeCmd(Device device, String channelId, String stream, String callId) throws InvalidArgumentException, ParseException, SipException, SsrcTransactionNotFoundException { | |
| 666 | + streamByeCmd(device, channelId, stream, callId, null); | |
| 667 | + } | |
| 668 | + | |
| 669 | + /** | |
| 670 | + * 视频流停止 | |
| 671 | + */ | |
| 672 | + @Override | |
| 673 | + public void streamByeCmd(Device device, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException { | |
| 674 | + if (device == null) { | |
| 675 | + logger.warn("[发送BYE] device为null"); | |
| 676 | + return; | |
| 677 | + } | |
| 678 | + List<SsrcTransaction> ssrcTransactionList = streamSession.getSsrcTransactionForAll(device.getDeviceId(), channelId, callId, stream); | |
| 679 | + if (ssrcTransactionList == null || ssrcTransactionList.isEmpty()) { | |
| 680 | + logger.info("[发送BYE] 未找到事务信息,设备: device: {}, channel: {}", device.getDeviceId(), channelId); | |
| 681 | + throw new SsrcTransactionNotFoundException(device.getDeviceId(), channelId, callId, stream); | |
| 682 | + } | |
| 683 | + | |
| 684 | + for (SsrcTransaction ssrcTransaction : ssrcTransactionList) { | |
| 685 | + logger.info("[发送BYE] 设备: device: {}, channel: {}, callId: {}", device.getDeviceId(), channelId, ssrcTransaction.getCallId()); | |
| 686 | + mediaServerService.releaseSsrc(ssrcTransaction.getMediaServerId(), ssrcTransaction.getSsrc()); | |
| 687 | + | |
| 688 | + mediaServerService.closeRTPServer(ssrcTransaction.getMediaServerId(), ssrcTransaction.getStream()); | |
| 689 | + streamSession.removeByCallId(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId(), ssrcTransaction.getCallId()); | |
| 690 | + Request byteRequest = headerProvider.createByteRequest(device, channelId, ssrcTransaction.getSipTransactionInfo()); | |
| 691 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), byteRequest, null, okEvent); | |
| 692 | + } | |
| 693 | + } | |
| 694 | + | |
| 695 | + @Override | |
| 696 | + public void streamByeCmd(Device device, String channelId, SipTransactionInfo sipTransactionInfo, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException { | |
| 697 | + Request byteRequest = headerProvider.createByteRequest(device, channelId, sipTransactionInfo); | |
| 698 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), byteRequest, null, okEvent); | |
| 699 | + } | |
| 700 | + | |
| 701 | + @Override | |
| 702 | + public void streamByeCmdForDeviceInvite(Device device, String channelId, SipTransactionInfo sipTransactionInfo, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException { | |
| 703 | + Request byteRequest = headerProvider.createByteRequestForDeviceInvite(device, channelId, sipTransactionInfo); | |
| 704 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), byteRequest, null, okEvent); | |
| 705 | + } | |
| 706 | + | |
| 707 | + /** | |
| 708 | + * 语音广播 | |
| 709 | + * | |
| 710 | + * @param device 视频设备 | |
| 711 | + */ | |
| 712 | + @Override | |
| 713 | + public void audioBroadcastCmd(Device device, String channelId, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 714 | + StringBuffer broadcastXml = new StringBuffer(200); | |
| 715 | + String charset = device.getCharset(); | |
| 716 | + broadcastXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 717 | + broadcastXml.append("<Notify>\r\n"); | |
| 718 | + broadcastXml.append("<CmdType>Broadcast</CmdType>\r\n"); | |
| 719 | + broadcastXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); | |
| 720 | + broadcastXml.append("<SourceID>" + sipConfig.getId() + "</SourceID>\r\n"); | |
| 721 | + broadcastXml.append("<TargetID>" + channelId + "</TargetID>\r\n"); | |
| 722 | + broadcastXml.append("</Notify>\r\n"); | |
| 723 | + | |
| 724 | + Request request = headerProvider.createMessageRequest(device, broadcastXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 725 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, okEvent); | |
| 726 | + | |
| 727 | + } | |
| 728 | + | |
| 729 | + | |
| 730 | + /** | |
| 731 | + * 音视频录像控制 | |
| 732 | + * | |
| 733 | + * @param device 视频设备 | |
| 734 | + * @param channelId 预览通道 | |
| 735 | + * @param recordCmdStr 录像命令:Record / StopRecord | |
| 736 | + */ | |
| 737 | + @Override | |
| 738 | + public void recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 739 | + StringBuffer cmdXml = new StringBuffer(200); | |
| 740 | + String charset = device.getCharset(); | |
| 741 | + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 742 | + cmdXml.append("<Control>\r\n"); | |
| 743 | + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n"); | |
| 744 | + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 745 | + if (ObjectUtils.isEmpty(channelId)) { | |
| 746 | + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 747 | + } else { | |
| 748 | + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 749 | + } | |
| 750 | + cmdXml.append("<RecordCmd>" + recordCmdStr + "</RecordCmd>\r\n"); | |
| 751 | + cmdXml.append("</Control>\r\n"); | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 756 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent); | |
| 757 | + } | |
| 758 | + | |
| 759 | + /** | |
| 760 | + * 远程启动控制命令 | |
| 761 | + * | |
| 762 | + * @param device 视频设备 | |
| 763 | + */ | |
| 764 | + @Override | |
| 765 | + public void teleBootCmd(Device device) throws InvalidArgumentException, SipException, ParseException { | |
| 766 | + | |
| 767 | + StringBuffer cmdXml = new StringBuffer(200); | |
| 768 | + String charset = device.getCharset(); | |
| 769 | + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 770 | + cmdXml.append("<Control>\r\n"); | |
| 771 | + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n"); | |
| 772 | + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 773 | + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 774 | + cmdXml.append("<TeleBoot>Boot</TeleBoot>\r\n"); | |
| 775 | + cmdXml.append("</Control>\r\n"); | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 780 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request); | |
| 781 | + } | |
| 782 | + | |
| 783 | + /** | |
| 784 | + * 报警布防/撤防命令 | |
| 785 | + * | |
| 786 | + * @param device 视频设备 | |
| 787 | + * @param guardCmdStr "SetGuard"/"ResetGuard" | |
| 788 | + */ | |
| 789 | + @Override | |
| 790 | + public void guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 791 | + | |
| 792 | + StringBuffer cmdXml = new StringBuffer(200); | |
| 793 | + String charset = device.getCharset(); | |
| 794 | + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 795 | + cmdXml.append("<Control>\r\n"); | |
| 796 | + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n"); | |
| 797 | + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 798 | + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 799 | + cmdXml.append("<GuardCmd>" + guardCmdStr + "</GuardCmd>\r\n"); | |
| 800 | + cmdXml.append("</Control>\r\n"); | |
| 801 | + | |
| 802 | + | |
| 803 | + | |
| 804 | + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 805 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent); | |
| 806 | + } | |
| 807 | + | |
| 808 | + /** | |
| 809 | + * 报警复位命令 | |
| 810 | + * | |
| 811 | + * @param device 视频设备 | |
| 812 | + */ | |
| 813 | + @Override | |
| 814 | + public void alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 815 | + | |
| 816 | + StringBuffer cmdXml = new StringBuffer(200); | |
| 817 | + String charset = device.getCharset(); | |
| 818 | + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 819 | + cmdXml.append("<Control>\r\n"); | |
| 820 | + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n"); | |
| 821 | + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 822 | + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 823 | + cmdXml.append("<AlarmCmd>ResetAlarm</AlarmCmd>\r\n"); | |
| 824 | + if (!ObjectUtils.isEmpty(alarmMethod) || !ObjectUtils.isEmpty(alarmType)) { | |
| 825 | + cmdXml.append("<Info>\r\n"); | |
| 826 | + } | |
| 827 | + if (!ObjectUtils.isEmpty(alarmMethod)) { | |
| 828 | + cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n"); | |
| 829 | + } | |
| 830 | + if (!ObjectUtils.isEmpty(alarmType)) { | |
| 831 | + cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n"); | |
| 832 | + } | |
| 833 | + if (!ObjectUtils.isEmpty(alarmMethod) || !ObjectUtils.isEmpty(alarmType)) { | |
| 834 | + cmdXml.append("</Info>\r\n"); | |
| 835 | + } | |
| 836 | + cmdXml.append("</Control>\r\n"); | |
| 837 | + | |
| 838 | + | |
| 839 | + | |
| 840 | + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 841 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent); | |
| 842 | + } | |
| 843 | + | |
| 844 | + /** | |
| 845 | + * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧 | |
| 846 | + * | |
| 847 | + * @param device 视频设备 | |
| 848 | + * @param channelId 预览通道 | |
| 849 | + */ | |
| 850 | + @Override | |
| 851 | + public void iFrameCmd(Device device, String channelId) throws InvalidArgumentException, SipException, ParseException { | |
| 852 | + | |
| 853 | + StringBuffer cmdXml = new StringBuffer(200); | |
| 854 | + String charset = device.getCharset(); | |
| 855 | + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 856 | + cmdXml.append("<Control>\r\n"); | |
| 857 | + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n"); | |
| 858 | + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 859 | + if (ObjectUtils.isEmpty(channelId)) { | |
| 860 | + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 861 | + } else { | |
| 862 | + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 863 | + } | |
| 864 | + cmdXml.append("<IFameCmd>Send</IFameCmd>\r\n"); | |
| 865 | + cmdXml.append("</Control>\r\n"); | |
| 866 | + | |
| 867 | + | |
| 868 | + | |
| 869 | + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 870 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request); | |
| 871 | + } | |
| 872 | + | |
| 873 | + /** | |
| 874 | + * 看守位控制命令 | |
| 875 | + * | |
| 876 | + * @param device 视频设备 | |
| 877 | + * @param channelId 通道id,非通道则是设备本身 | |
| 878 | + * @param enabled 看守位使能:1 = 开启,0 = 关闭 | |
| 879 | + * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s) | |
| 880 | + * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255 | |
| 881 | + */ | |
| 882 | + @Override | |
| 883 | + public void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 884 | + | |
| 885 | + StringBuffer cmdXml = new StringBuffer(200); | |
| 886 | + String charset = device.getCharset(); | |
| 887 | + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 888 | + cmdXml.append("<Control>\r\n"); | |
| 889 | + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n"); | |
| 890 | + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 891 | + if (ObjectUtils.isEmpty(channelId)) { | |
| 892 | + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 893 | + } else { | |
| 894 | + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 895 | + } | |
| 896 | + cmdXml.append("<HomePosition>\r\n"); | |
| 897 | + if (NumericUtil.isInteger(enabled) && (!enabled.equals("0"))) { | |
| 898 | + cmdXml.append("<Enabled>1</Enabled>\r\n"); | |
| 899 | + if (NumericUtil.isInteger(resetTime)) { | |
| 900 | + cmdXml.append("<ResetTime>" + resetTime + "</ResetTime>\r\n"); | |
| 901 | + } else { | |
| 902 | + cmdXml.append("<ResetTime>0</ResetTime>\r\n"); | |
| 903 | + } | |
| 904 | + if (NumericUtil.isInteger(presetIndex)) { | |
| 905 | + cmdXml.append("<PresetIndex>" + presetIndex + "</PresetIndex>\r\n"); | |
| 906 | + } else { | |
| 907 | + cmdXml.append("<PresetIndex>0</PresetIndex>\r\n"); | |
| 908 | + } | |
| 909 | + } else { | |
| 910 | + cmdXml.append("<Enabled>0</Enabled>\r\n"); | |
| 911 | + } | |
| 912 | + cmdXml.append("</HomePosition>\r\n"); | |
| 913 | + cmdXml.append("</Control>\r\n"); | |
| 914 | + | |
| 915 | + | |
| 916 | + | |
| 917 | + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 918 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent); | |
| 919 | + } | |
| 920 | + | |
| 921 | + /** | |
| 922 | + * 设备配置命令 | |
| 923 | + * | |
| 924 | + * @param device 视频设备 | |
| 925 | + */ | |
| 926 | + @Override | |
| 927 | + public void deviceConfigCmd(Device device) { | |
| 928 | + // TODO Auto-generated method stub | |
| 929 | + } | |
| 930 | + | |
| 931 | + /** | |
| 932 | + * 设备配置命令:basicParam | |
| 933 | + * | |
| 934 | + * @param device 视频设备 | |
| 935 | + * @param channelId 通道编码(可选) | |
| 936 | + * @param name 设备/通道名称(可选) | |
| 937 | + * @param expiration 注册过期时间(可选) | |
| 938 | + * @param heartBeatInterval 心跳间隔时间(可选) | |
| 939 | + * @param heartBeatCount 心跳超时次数(可选) | |
| 940 | + */ | |
| 941 | + @Override | |
| 942 | + public void deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, | |
| 943 | + String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 944 | + | |
| 945 | + StringBuffer cmdXml = new StringBuffer(200); | |
| 946 | + String charset = device.getCharset(); | |
| 947 | + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 948 | + cmdXml.append("<Control>\r\n"); | |
| 949 | + cmdXml.append("<CmdType>DeviceConfig</CmdType>\r\n"); | |
| 950 | + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 951 | + if (ObjectUtils.isEmpty(channelId)) { | |
| 952 | + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 953 | + } else { | |
| 954 | + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 955 | + } | |
| 956 | + cmdXml.append("<BasicParam>\r\n"); | |
| 957 | + if (!ObjectUtils.isEmpty(name)) { | |
| 958 | + cmdXml.append("<Name>" + name + "</Name>\r\n"); | |
| 959 | + } | |
| 960 | + if (NumericUtil.isInteger(expiration)) { | |
| 961 | + if (Integer.valueOf(expiration) > 0) { | |
| 962 | + cmdXml.append("<Expiration>" + expiration + "</Expiration>\r\n"); | |
| 963 | + } | |
| 964 | + } | |
| 965 | + if (NumericUtil.isInteger(heartBeatInterval)) { | |
| 966 | + if (Integer.valueOf(heartBeatInterval) > 0) { | |
| 967 | + cmdXml.append("<HeartBeatInterval>" + heartBeatInterval + "</HeartBeatInterval>\r\n"); | |
| 968 | + } | |
| 969 | + } | |
| 970 | + if (NumericUtil.isInteger(heartBeatCount)) { | |
| 971 | + if (Integer.valueOf(heartBeatCount) > 0) { | |
| 972 | + cmdXml.append("<HeartBeatCount>" + heartBeatCount + "</HeartBeatCount>\r\n"); | |
| 973 | + } | |
| 974 | + } | |
| 975 | + cmdXml.append("</BasicParam>\r\n"); | |
| 976 | + cmdXml.append("</Control>\r\n"); | |
| 977 | + | |
| 978 | + | |
| 979 | + | |
| 980 | + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 981 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); | |
| 982 | + } | |
| 983 | + | |
| 984 | + /** | |
| 985 | + * 查询设备状态 | |
| 986 | + * | |
| 987 | + * @param device 视频设备 | |
| 988 | + */ | |
| 989 | + @Override | |
| 990 | + public void deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 991 | + | |
| 992 | + String charset = device.getCharset(); | |
| 993 | + StringBuffer catalogXml = new StringBuffer(200); | |
| 994 | + catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 995 | + catalogXml.append("<Query>\r\n"); | |
| 996 | + catalogXml.append("<CmdType>DeviceStatus</CmdType>\r\n"); | |
| 997 | + catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 998 | + catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 999 | + catalogXml.append("</Query>\r\n"); | |
| 1000 | + | |
| 1001 | + | |
| 1002 | + | |
| 1003 | + Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 1004 | + | |
| 1005 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); | |
| 1006 | + } | |
| 1007 | + | |
| 1008 | + /** | |
| 1009 | + * 查询设备信息 | |
| 1010 | + * | |
| 1011 | + * @param device 视频设备 | |
| 1012 | + */ | |
| 1013 | + @Override | |
| 1014 | + public void deviceInfoQuery(Device device) throws InvalidArgumentException, SipException, ParseException { | |
| 1015 | + | |
| 1016 | + StringBuffer catalogXml = new StringBuffer(200); | |
| 1017 | + String charset = device.getCharset(); | |
| 1018 | + catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 1019 | + catalogXml.append("<Query>\r\n"); | |
| 1020 | + catalogXml.append("<CmdType>DeviceInfo</CmdType>\r\n"); | |
| 1021 | + catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 1022 | + catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 1023 | + catalogXml.append("</Query>\r\n"); | |
| 1024 | + | |
| 1025 | + | |
| 1026 | + | |
| 1027 | + Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 1028 | + | |
| 1029 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request); | |
| 1030 | + | |
| 1031 | + } | |
| 1032 | + | |
| 1033 | + /** | |
| 1034 | + * 查询目录列表 | |
| 1035 | + * | |
| 1036 | + * @param device 视频设备 | |
| 1037 | + */ | |
| 1038 | + @Override | |
| 1039 | + public void catalogQuery(Device device, int sn, SipSubscribe.Event errorEvent) throws SipException, InvalidArgumentException, ParseException { | |
| 1040 | + | |
| 1041 | + StringBuffer catalogXml = new StringBuffer(200); | |
| 1042 | + String charset = device.getCharset(); | |
| 1043 | + catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 1044 | + catalogXml.append("<Query>\r\n"); | |
| 1045 | + catalogXml.append(" <CmdType>Catalog</CmdType>\r\n"); | |
| 1046 | + catalogXml.append(" <SN>" + sn + "</SN>\r\n"); | |
| 1047 | + catalogXml.append(" <DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 1048 | + catalogXml.append("</Query>\r\n"); | |
| 1049 | + | |
| 1050 | + | |
| 1051 | + | |
| 1052 | + Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 1053 | + | |
| 1054 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); | |
| 1055 | + } | |
| 1056 | + | |
| 1057 | + /** | |
| 1058 | + * 查询录像信息 | |
| 1059 | + * | |
| 1060 | + * @param device 视频设备 | |
| 1061 | + * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss | |
| 1062 | + * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss | |
| 1063 | + */ | |
| 1064 | + @Override | |
| 1065 | + public void recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, Integer secrecy, String type, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 1066 | + if (secrecy == null) { | |
| 1067 | + secrecy = 0; | |
| 1068 | + } | |
| 1069 | + if (type == null) { | |
| 1070 | + type = "all"; | |
| 1071 | + } | |
| 1072 | + | |
| 1073 | + StringBuffer recordInfoXml = new StringBuffer(200); | |
| 1074 | + String charset = device.getCharset(); | |
| 1075 | + recordInfoXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 1076 | + recordInfoXml.append("<Query>\r\n"); | |
| 1077 | + recordInfoXml.append("<CmdType>RecordInfo</CmdType>\r\n"); | |
| 1078 | + recordInfoXml.append("<SN>" + sn + "</SN>\r\n"); | |
| 1079 | + recordInfoXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 1080 | + if (startTime != null) { | |
| 1081 | + recordInfoXml.append("<StartTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(startTime) + "</StartTime>\r\n"); | |
| 1082 | + } | |
| 1083 | + if (endTime != null) { | |
| 1084 | + recordInfoXml.append("<EndTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(endTime) + "</EndTime>\r\n"); | |
| 1085 | + } | |
| 1086 | + if (secrecy != null) { | |
| 1087 | + recordInfoXml.append("<Secrecy> " + secrecy + " </Secrecy>\r\n"); | |
| 1088 | + } | |
| 1089 | + if (type != null) { | |
| 1090 | + // 大华NVR要求必须增加一个值为all的文本元素节点Type | |
| 1091 | + recordInfoXml.append("<Type>" + type + "</Type>\r\n"); | |
| 1092 | + } | |
| 1093 | + recordInfoXml.append("</Query>\r\n"); | |
| 1094 | + | |
| 1095 | + | |
| 1096 | + | |
| 1097 | + Request request = headerProvider.createMessageRequest(device, recordInfoXml.toString(), | |
| 1098 | + SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 1099 | + | |
| 1100 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, okEvent); | |
| 1101 | + } | |
| 1102 | + | |
| 1103 | + /** | |
| 1104 | + * 查询报警信息 | |
| 1105 | + * | |
| 1106 | + * @param device 视频设备 | |
| 1107 | + * @param startPriority 报警起始级别(可选) | |
| 1108 | + * @param endPriority 报警终止级别(可选) | |
| 1109 | + * @param alarmMethod 报警方式条件(可选) | |
| 1110 | + * @param alarmType 报警类型 | |
| 1111 | + * @param startTime 报警发生起始时间(可选) | |
| 1112 | + * @param endTime 报警发生终止时间(可选) | |
| 1113 | + * @return true = 命令发送成功 | |
| 1114 | + */ | |
| 1115 | + @Override | |
| 1116 | + public void alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod, String alarmType, | |
| 1117 | + String startTime, String endTime, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 1118 | + | |
| 1119 | + StringBuffer cmdXml = new StringBuffer(200); | |
| 1120 | + String charset = device.getCharset(); | |
| 1121 | + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 1122 | + cmdXml.append("<Query>\r\n"); | |
| 1123 | + cmdXml.append("<CmdType>Alarm</CmdType>\r\n"); | |
| 1124 | + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 1125 | + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 1126 | + if (!ObjectUtils.isEmpty(startPriority)) { | |
| 1127 | + cmdXml.append("<StartAlarmPriority>" + startPriority + "</StartAlarmPriority>\r\n"); | |
| 1128 | + } | |
| 1129 | + if (!ObjectUtils.isEmpty(endPriority)) { | |
| 1130 | + cmdXml.append("<EndAlarmPriority>" + endPriority + "</EndAlarmPriority>\r\n"); | |
| 1131 | + } | |
| 1132 | + if (!ObjectUtils.isEmpty(alarmMethod)) { | |
| 1133 | + cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n"); | |
| 1134 | + } | |
| 1135 | + if (!ObjectUtils.isEmpty(alarmType)) { | |
| 1136 | + cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n"); | |
| 1137 | + } | |
| 1138 | + if (!ObjectUtils.isEmpty(startTime)) { | |
| 1139 | + cmdXml.append("<StartAlarmTime>" + startTime + "</StartAlarmTime>\r\n"); | |
| 1140 | + } | |
| 1141 | + if (!ObjectUtils.isEmpty(endTime)) { | |
| 1142 | + cmdXml.append("<EndAlarmTime>" + endTime + "</EndAlarmTime>\r\n"); | |
| 1143 | + } | |
| 1144 | + cmdXml.append("</Query>\r\n"); | |
| 1145 | + | |
| 1146 | + | |
| 1147 | + | |
| 1148 | + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 1149 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); | |
| 1150 | + } | |
| 1151 | + | |
| 1152 | + /** | |
| 1153 | + * 查询设备配置 | |
| 1154 | + * | |
| 1155 | + * @param device 视频设备 | |
| 1156 | + * @param channelId 通道编码(可选) | |
| 1157 | + * @param configType 配置类型: | |
| 1158 | + */ | |
| 1159 | + @Override | |
| 1160 | + public void deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 1161 | + | |
| 1162 | + StringBuffer cmdXml = new StringBuffer(200); | |
| 1163 | + String charset = device.getCharset(); | |
| 1164 | + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 1165 | + cmdXml.append("<Query>\r\n"); | |
| 1166 | + cmdXml.append("<CmdType>ConfigDownload</CmdType>\r\n"); | |
| 1167 | + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 1168 | + if (ObjectUtils.isEmpty(channelId)) { | |
| 1169 | + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 1170 | + } else { | |
| 1171 | + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 1172 | + } | |
| 1173 | + cmdXml.append("<ConfigType>" + configType + "</ConfigType>\r\n"); | |
| 1174 | + cmdXml.append("</Query>\r\n"); | |
| 1175 | + | |
| 1176 | + | |
| 1177 | + | |
| 1178 | + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 1179 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); | |
| 1180 | + } | |
| 1181 | + | |
| 1182 | + /** | |
| 1183 | + * 查询设备预置位置 | |
| 1184 | + * | |
| 1185 | + * @param device 视频设备 | |
| 1186 | + */ | |
| 1187 | + @Override | |
| 1188 | + public void presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 1189 | + | |
| 1190 | + StringBuffer cmdXml = new StringBuffer(200); | |
| 1191 | + String charset = device.getCharset(); | |
| 1192 | + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 1193 | + cmdXml.append("<Query>\r\n"); | |
| 1194 | + cmdXml.append("<CmdType>PresetQuery</CmdType>\r\n"); | |
| 1195 | + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 1196 | + if (ObjectUtils.isEmpty(channelId)) { | |
| 1197 | + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 1198 | + } else { | |
| 1199 | + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 1200 | + } | |
| 1201 | + cmdXml.append("</Query>\r\n"); | |
| 1202 | + | |
| 1203 | + | |
| 1204 | + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 1205 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); | |
| 1206 | + } | |
| 1207 | + | |
| 1208 | + /** | |
| 1209 | + * 查询移动设备位置数据 | |
| 1210 | + * | |
| 1211 | + * @param device 视频设备 | |
| 1212 | + */ | |
| 1213 | + @Override | |
| 1214 | + public void mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 1215 | + | |
| 1216 | + StringBuffer mobilePostitionXml = new StringBuffer(200); | |
| 1217 | + String charset = device.getCharset(); | |
| 1218 | + mobilePostitionXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 1219 | + mobilePostitionXml.append("<Query>\r\n"); | |
| 1220 | + mobilePostitionXml.append("<CmdType>MobilePosition</CmdType>\r\n"); | |
| 1221 | + mobilePostitionXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 1222 | + mobilePostitionXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 1223 | + mobilePostitionXml.append("<Interval>60</Interval>\r\n"); | |
| 1224 | + mobilePostitionXml.append("</Query>\r\n"); | |
| 1225 | + | |
| 1226 | + | |
| 1227 | + | |
| 1228 | + Request request = headerProvider.createMessageRequest(device, mobilePostitionXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 1229 | + | |
| 1230 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); | |
| 1231 | + | |
| 1232 | + } | |
| 1233 | + | |
| 1234 | + /** | |
| 1235 | + * 订阅、取消订阅移动位置 | |
| 1236 | + * | |
| 1237 | + * @param device 视频设备 | |
| 1238 | + * @return true = 命令发送成功 | |
| 1239 | + */ | |
| 1240 | + @Override | |
| 1241 | + public SIPRequest mobilePositionSubscribe(Device device, SIPRequest requestOld, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 1242 | + | |
| 1243 | + StringBuffer subscribePostitionXml = new StringBuffer(200); | |
| 1244 | + String charset = device.getCharset(); | |
| 1245 | + subscribePostitionXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 1246 | + subscribePostitionXml.append("<Query>\r\n"); | |
| 1247 | + subscribePostitionXml.append("<CmdType>MobilePosition</CmdType>\r\n"); | |
| 1248 | + subscribePostitionXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 1249 | + subscribePostitionXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 1250 | + if (device.getSubscribeCycleForMobilePosition() > 0) { | |
| 1251 | + subscribePostitionXml.append("<Interval>" + device.getMobilePositionSubmissionInterval() + "</Interval>\r\n"); | |
| 1252 | + } | |
| 1253 | + subscribePostitionXml.append("</Query>\r\n"); | |
| 1254 | + | |
| 1255 | + CallIdHeader callIdHeader; | |
| 1256 | + | |
| 1257 | + if (requestOld != null) { | |
| 1258 | + callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId()); | |
| 1259 | + } else { | |
| 1260 | + callIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()); | |
| 1261 | + } | |
| 1262 | + SIPRequest request = (SIPRequest) headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), requestOld, device.getSubscribeCycleForMobilePosition(), "presence",callIdHeader); //Position;id=" + tm.substring(tm.length() - 4)); | |
| 1263 | + | |
| 1264 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, okEvent); | |
| 1265 | + return request; | |
| 1266 | + } | |
| 1267 | + | |
| 1268 | + /** | |
| 1269 | + * 订阅、取消订阅报警信息 | |
| 1270 | + * | |
| 1271 | + * @param device 视频设备 | |
| 1272 | + * @param expires 订阅过期时间(0 = 取消订阅) | |
| 1273 | + * @param startPriority 报警起始级别(可选) | |
| 1274 | + * @param endPriority 报警终止级别(可选) | |
| 1275 | + * @param alarmMethod 报警方式条件(可选) | |
| 1276 | + * @param alarmType 报警类型 | |
| 1277 | + * @param startTime 报警发生起始时间(可选) | |
| 1278 | + * @param endTime 报警发生终止时间(可选) | |
| 1279 | + * @return true = 命令发送成功 | |
| 1280 | + */ | |
| 1281 | + @Override | |
| 1282 | + public void alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String startTime, String endTime) throws InvalidArgumentException, SipException, ParseException { | |
| 1283 | + | |
| 1284 | + StringBuffer cmdXml = new StringBuffer(200); | |
| 1285 | + String charset = device.getCharset(); | |
| 1286 | + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 1287 | + cmdXml.append("<Query>\r\n"); | |
| 1288 | + cmdXml.append("<CmdType>Alarm</CmdType>\r\n"); | |
| 1289 | + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 1290 | + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 1291 | + if (!ObjectUtils.isEmpty(startPriority)) { | |
| 1292 | + cmdXml.append("<StartAlarmPriority>" + startPriority + "</StartAlarmPriority>\r\n"); | |
| 1293 | + } | |
| 1294 | + if (!ObjectUtils.isEmpty(endPriority)) { | |
| 1295 | + cmdXml.append("<EndAlarmPriority>" + endPriority + "</EndAlarmPriority>\r\n"); | |
| 1296 | + } | |
| 1297 | + if (!ObjectUtils.isEmpty(alarmMethod)) { | |
| 1298 | + cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n"); | |
| 1299 | + } | |
| 1300 | + if (!ObjectUtils.isEmpty(startTime)) { | |
| 1301 | + cmdXml.append("<StartAlarmTime>" + startTime + "</StartAlarmTime>\r\n"); | |
| 1302 | + } | |
| 1303 | + if (!ObjectUtils.isEmpty(endTime)) { | |
| 1304 | + cmdXml.append("<EndAlarmTime>" + endTime + "</EndAlarmTime>\r\n"); | |
| 1305 | + } | |
| 1306 | + cmdXml.append("</Query>\r\n"); | |
| 1307 | + | |
| 1308 | + | |
| 1309 | + | |
| 1310 | + Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), null, expires, "presence",sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 1311 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request); | |
| 1312 | + | |
| 1313 | + } | |
| 1314 | + | |
| 1315 | + @Override | |
| 1316 | + public SIPRequest catalogSubscribe(Device device, SIPRequest requestOld, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 1317 | + | |
| 1318 | + StringBuffer cmdXml = new StringBuffer(200); | |
| 1319 | + String charset = device.getCharset(); | |
| 1320 | + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 1321 | + cmdXml.append("<Query>\r\n"); | |
| 1322 | + cmdXml.append("<CmdType>Catalog</CmdType>\r\n"); | |
| 1323 | + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 1324 | + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 1325 | + cmdXml.append("</Query>\r\n"); | |
| 1326 | + | |
| 1327 | + CallIdHeader callIdHeader; | |
| 1328 | + | |
| 1329 | + if (requestOld != null) { | |
| 1330 | + callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId()); | |
| 1331 | + } else { | |
| 1332 | + callIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()); | |
| 1333 | + } | |
| 1334 | + | |
| 1335 | + // 有效时间默认为60秒以上 | |
| 1336 | + SIPRequest request = (SIPRequest) headerProvider.createSubscribeRequest(device, cmdXml.toString(), requestOld, device.getSubscribeCycleForCatalog(), "Catalog", | |
| 1337 | + callIdHeader); | |
| 1338 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, okEvent); | |
| 1339 | + return request; | |
| 1340 | + } | |
| 1341 | + | |
| 1342 | + @Override | |
| 1343 | + public void dragZoomCmd(Device device, String channelId, String cmdString) throws InvalidArgumentException, SipException, ParseException { | |
| 1344 | + | |
| 1345 | + StringBuffer dragXml = new StringBuffer(200); | |
| 1346 | + String charset = device.getCharset(); | |
| 1347 | + dragXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 1348 | + dragXml.append("<Control>\r\n"); | |
| 1349 | + dragXml.append("<CmdType>DeviceControl</CmdType>\r\n"); | |
| 1350 | + dragXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 1351 | + if (ObjectUtils.isEmpty(channelId)) { | |
| 1352 | + dragXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 1353 | + } else { | |
| 1354 | + dragXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 1355 | + } | |
| 1356 | + dragXml.append(cmdString); | |
| 1357 | + dragXml.append("</Control>\r\n"); | |
| 1358 | + | |
| 1359 | + Request request = headerProvider.createMessageRequest(device, dragXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 1360 | + logger.debug("拉框信令: " + request.toString()); | |
| 1361 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()),request); | |
| 1362 | + } | |
| 1363 | + | |
| 1364 | + | |
| 1365 | + | |
| 1366 | + /** | |
| 1367 | + * 回放暂停 | |
| 1368 | + */ | |
| 1369 | + @Override | |
| 1370 | + public void playPauseCmd(Device device, StreamInfo streamInfo) throws InvalidArgumentException, ParseException, SipException { | |
| 1371 | + StringBuffer content = new StringBuffer(200); | |
| 1372 | + content.append("PAUSE RTSP/1.0\r\n"); | |
| 1373 | + content.append("CSeq: " + getInfoCseq() + "\r\n"); | |
| 1374 | + content.append("PauseTime: now\r\n"); | |
| 1375 | + | |
| 1376 | + playbackControlCmd(device, streamInfo, content.toString(), null, null); | |
| 1377 | + } | |
| 1378 | + | |
| 1379 | + | |
| 1380 | + /** | |
| 1381 | + * 回放恢复 | |
| 1382 | + */ | |
| 1383 | + @Override | |
| 1384 | + public void playResumeCmd(Device device, StreamInfo streamInfo) throws InvalidArgumentException, ParseException, SipException { | |
| 1385 | + StringBuffer content = new StringBuffer(200); | |
| 1386 | + content.append("PLAY RTSP/1.0\r\n"); | |
| 1387 | + content.append("CSeq: " + getInfoCseq() + "\r\n"); | |
| 1388 | + content.append("Range: npt=now-\r\n"); | |
| 1389 | + | |
| 1390 | + playbackControlCmd(device, streamInfo, content.toString(), null, null); | |
| 1391 | + } | |
| 1392 | + | |
| 1393 | + /** | |
| 1394 | + * 回放拖动播放 | |
| 1395 | + */ | |
| 1396 | + @Override | |
| 1397 | + public void playSeekCmd(Device device, StreamInfo streamInfo, long seekTime) throws InvalidArgumentException, ParseException, SipException { | |
| 1398 | + StringBuffer content = new StringBuffer(200); | |
| 1399 | + content.append("PLAY RTSP/1.0\r\n"); | |
| 1400 | + content.append("CSeq: " + getInfoCseq() + "\r\n"); | |
| 1401 | + content.append("Range: npt=" + Math.abs(seekTime) + "-\r\n"); | |
| 1402 | + | |
| 1403 | + playbackControlCmd(device, streamInfo, content.toString(), null, null); | |
| 1404 | + } | |
| 1405 | + | |
| 1406 | + /** | |
| 1407 | + * 回放倍速播放 | |
| 1408 | + */ | |
| 1409 | + @Override | |
| 1410 | + public void playSpeedCmd(Device device, StreamInfo streamInfo, Double speed) throws InvalidArgumentException, ParseException, SipException { | |
| 1411 | + StringBuffer content = new StringBuffer(200); | |
| 1412 | + content.append("PLAY RTSP/1.0\r\n"); | |
| 1413 | + content.append("CSeq: " + getInfoCseq() + "\r\n"); | |
| 1414 | + content.append("Scale: " + String.format("%.6f", speed) + "\r\n"); | |
| 1415 | + | |
| 1416 | + playbackControlCmd(device, streamInfo, content.toString(), null, null); | |
| 1417 | + } | |
| 1418 | + | |
| 1419 | + private int getInfoCseq() { | |
| 1420 | + return (int) ((Math.random() * 9 + 1) * Math.pow(10, 8)); | |
| 1421 | + } | |
| 1422 | + | |
| 1423 | + @Override | |
| 1424 | + public void playbackControlCmd(Device device, StreamInfo streamInfo, String content, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException, InvalidArgumentException, ParseException { | |
| 1425 | + | |
| 1426 | + SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(device.getDeviceId(), streamInfo.getChannelId(), null, streamInfo.getStream()); | |
| 1427 | + if (ssrcTransaction == null) { | |
| 1428 | + logger.info("[回放控制]未找到视频流信息,设备:{}, 流ID: {}", device.getDeviceId(), streamInfo.getStream()); | |
| 1429 | + return; | |
| 1430 | + } | |
| 1431 | + | |
| 1432 | + SIPRequest request = headerProvider.createInfoRequest(device, streamInfo.getChannelId(), content.toString(), ssrcTransaction.getSipTransactionInfo()); | |
| 1433 | + if (request == null) { | |
| 1434 | + logger.info("[回放控制]构建Request信息失败,设备:{}, 流ID: {}", device.getDeviceId(), streamInfo.getStream()); | |
| 1435 | + return; | |
| 1436 | + } | |
| 1437 | + | |
| 1438 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, okEvent); | |
| 1439 | + } | |
| 1440 | + | |
| 1441 | + @Override | |
| 1442 | + public void sendAlarmMessage(Device device, DeviceAlarm deviceAlarm) throws InvalidArgumentException, SipException, ParseException { | |
| 1443 | + if (device == null) { | |
| 1444 | + return; | |
| 1445 | + } | |
| 1446 | + logger.info("[发送报警通知]设备: {}/{}->{},{}", device.getDeviceId(), deviceAlarm.getChannelId(), | |
| 1447 | + deviceAlarm.getLongitude(), deviceAlarm.getLatitude()); | |
| 1448 | + | |
| 1449 | + String characterSet = device.getCharset(); | |
| 1450 | + StringBuffer deviceStatusXml = new StringBuffer(600); | |
| 1451 | + deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n"); | |
| 1452 | + deviceStatusXml.append("<Notify>\r\n"); | |
| 1453 | + deviceStatusXml.append("<CmdType>Alarm</CmdType>\r\n"); | |
| 1454 | + deviceStatusXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 1455 | + deviceStatusXml.append("<DeviceID>" + deviceAlarm.getChannelId() + "</DeviceID>\r\n"); | |
| 1456 | + deviceStatusXml.append("<AlarmPriority>" + deviceAlarm.getAlarmPriority() + "</AlarmPriority>\r\n"); | |
| 1457 | + deviceStatusXml.append("<AlarmMethod>" + deviceAlarm.getAlarmMethod() + "</AlarmMethod>\r\n"); | |
| 1458 | + deviceStatusXml.append("<AlarmTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(deviceAlarm.getAlarmTime()) + "</AlarmTime>\r\n"); | |
| 1459 | + deviceStatusXml.append("<AlarmDescription>" + deviceAlarm.getAlarmDescription() + "</AlarmDescription>\r\n"); | |
| 1460 | + deviceStatusXml.append("<Longitude>" + deviceAlarm.getLongitude() + "</Longitude>\r\n"); | |
| 1461 | + deviceStatusXml.append("<Latitude>" + deviceAlarm.getLatitude() + "</Latitude>\r\n"); | |
| 1462 | + deviceStatusXml.append("<info>\r\n"); | |
| 1463 | + deviceStatusXml.append("<AlarmType>" + deviceAlarm.getAlarmType() + "</AlarmType>\r\n"); | |
| 1464 | + deviceStatusXml.append("</info>\r\n"); | |
| 1465 | + deviceStatusXml.append("</Notify>\r\n"); | |
| 1466 | + | |
| 1467 | + | |
| 1468 | + Request request = headerProvider.createMessageRequest(device, deviceStatusXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | |
| 1469 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()),request); | |
| 1470 | + | |
| 1471 | + | |
| 1472 | + } | |
| 1473 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
| 1 | 1 | package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl; |
| 2 | 2 | |
| 3 | 3 | import com.alibaba.fastjson2.JSON; |
| 4 | +import com.genersoft.iot.vmp.common.InviteSessionType; | |
| 4 | 5 | import com.genersoft.iot.vmp.conf.DynamicTask; |
| 6 | +import com.genersoft.iot.vmp.conf.UserSetting; | |
| 7 | +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; | |
| 5 | 8 | import com.genersoft.iot.vmp.gb28181.SipLayer; |
| 6 | 9 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 7 | 10 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| 11 | +import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | |
| 8 | 12 | import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; |
| 9 | 13 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; |
| 10 | 14 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderPlarformProvider; |
| 11 | 15 | import com.genersoft.iot.vmp.gb28181.utils.SipUtils; |
| 16 | +import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; | |
| 17 | +import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; | |
| 18 | +import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; | |
| 12 | 19 | import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; |
| 13 | 20 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 21 | +import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam; | |
| 14 | 22 | import com.genersoft.iot.vmp.service.IMediaServerService; |
| 15 | 23 | import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; |
| 24 | +import com.genersoft.iot.vmp.service.bean.SSRCInfo; | |
| 16 | 25 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 17 | 26 | import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo; |
| 18 | 27 | import com.genersoft.iot.vmp.utils.DateUtil; |
| 19 | 28 | import com.genersoft.iot.vmp.utils.GitUtil; |
| 20 | 29 | import gov.nist.javax.sip.message.MessageFactoryImpl; |
| 21 | 30 | import gov.nist.javax.sip.message.SIPRequest; |
| 31 | +import gov.nist.javax.sip.message.SIPResponse; | |
| 22 | 32 | import org.slf4j.Logger; |
| 23 | 33 | import org.slf4j.LoggerFactory; |
| 24 | 34 | import org.springframework.beans.factory.annotation.Autowired; |
| ... | ... | @@ -28,6 +38,7 @@ import org.springframework.stereotype.Component; |
| 28 | 38 | import org.springframework.util.ObjectUtils; |
| 29 | 39 | |
| 30 | 40 | import javax.sip.InvalidArgumentException; |
| 41 | +import javax.sip.ResponseEvent; | |
| 31 | 42 | import javax.sip.SipException; |
| 32 | 43 | import javax.sip.SipFactory; |
| 33 | 44 | import javax.sip.header.CallIdHeader; |
| ... | ... | @@ -65,6 +76,16 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { |
| 65 | 76 | private SIPSender sipSender; |
| 66 | 77 | |
| 67 | 78 | @Autowired |
| 79 | + private ZlmHttpHookSubscribe subscribe; | |
| 80 | + | |
| 81 | + @Autowired | |
| 82 | + private UserSetting userSetting; | |
| 83 | + | |
| 84 | + | |
| 85 | + @Autowired | |
| 86 | + private VideoStreamSessionManager streamSession; | |
| 87 | + | |
| 88 | + @Autowired | |
| 68 | 89 | private DynamicTask dynamicTask; |
| 69 | 90 | |
| 70 | 91 | @Autowired |
| ... | ... | @@ -462,6 +483,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { |
| 462 | 483 | sipSender.transmitRequest(parentPlatform.getDeviceIp(), request); |
| 463 | 484 | } |
| 464 | 485 | |
| 486 | + | |
| 465 | 487 | /** |
| 466 | 488 | * 向上级回复DeviceStatus查询信息 |
| 467 | 489 | * @param parentPlatform 平台信息 |
| ... | ... | @@ -811,26 +833,129 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { |
| 811 | 833 | } |
| 812 | 834 | |
| 813 | 835 | @Override |
| 814 | - public void streamByeCmd(ParentPlatform parentPlatform, SendRtpItem sendRtpItem) throws SipException, InvalidArgumentException, ParseException { | |
| 836 | + public synchronized void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem) throws SipException, InvalidArgumentException, ParseException { | |
| 815 | 837 | if (sendRtpItem == null ) { |
| 816 | 838 | logger.info("[向上级发送BYE], sendRtpItem 为NULL"); |
| 817 | 839 | return; |
| 818 | 840 | } |
| 819 | - if (parentPlatform == null) { | |
| 841 | + if (platform == null) { | |
| 820 | 842 | logger.info("[向上级发送BYE], platform 为NULL"); |
| 821 | 843 | return; |
| 822 | 844 | } |
| 823 | - logger.info("[向上级发送BYE], {}/{}", parentPlatform.getServerGBId(), sendRtpItem.getChannelId()); | |
| 845 | + logger.info("[向上级发送BYE], {}/{}", platform.getServerGBId(), sendRtpItem.getChannelId()); | |
| 824 | 846 | String mediaServerId = sendRtpItem.getMediaServerId(); |
| 825 | 847 | MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); |
| 826 | 848 | if (mediaServerItem != null) { |
| 827 | 849 | mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc()); |
| 828 | - zlmServerFactory.closeRtpServer(mediaServerItem, sendRtpItem.getStreamId()); | |
| 850 | + zlmServerFactory.closeRtpServer(mediaServerItem, sendRtpItem.getStream()); | |
| 829 | 851 | } |
| 830 | - SIPRequest byeRequest = headerProviderPlatformProvider.createByeRequest(parentPlatform, sendRtpItem); | |
| 852 | + SIPRequest byeRequest = headerProviderPlatformProvider.createByeRequest(platform, sendRtpItem); | |
| 831 | 853 | if (byeRequest == null) { |
| 832 | 854 | logger.warn("[向上级发送bye]:无法创建 byeRequest"); |
| 833 | 855 | } |
| 834 | - sipSender.transmitRequest(parentPlatform.getDeviceIp(),byeRequest); | |
| 856 | + sipSender.transmitRequest(platform.getDeviceIp(),byeRequest); | |
| 857 | + } | |
| 858 | + | |
| 859 | + @Override | |
| 860 | + public void streamByeCmd(ParentPlatform platform, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException { | |
| 861 | + SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(platform.getServerGBId(), channelId, callId, stream); | |
| 862 | + if (ssrcTransaction == null) { | |
| 863 | + throw new SsrcTransactionNotFoundException(platform.getServerGBId(), channelId, callId, stream); | |
| 864 | + } | |
| 865 | + | |
| 866 | + mediaServerService.releaseSsrc(ssrcTransaction.getMediaServerId(), ssrcTransaction.getSsrc()); | |
| 867 | + mediaServerService.closeRTPServer(ssrcTransaction.getMediaServerId(), ssrcTransaction.getStream()); | |
| 868 | + streamSession.remove(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId(), ssrcTransaction.getStream()); | |
| 869 | + | |
| 870 | + Request byteRequest = headerProviderPlatformProvider.createByteRequest(platform, channelId, ssrcTransaction.getSipTransactionInfo()); | |
| 871 | + sipSender.transmitRequest(sipLayer.getLocalIp(platform.getDeviceIp()), byteRequest, null, okEvent); | |
| 872 | + } | |
| 873 | + | |
| 874 | + @Override | |
| 875 | + public void broadcastResultCmd(ParentPlatform platform, DeviceChannel deviceChannel, String sn, boolean result, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 876 | + if (platform == null || deviceChannel == null) { | |
| 877 | + return; | |
| 878 | + } | |
| 879 | + String characterSet = platform.getCharacterSet(); | |
| 880 | + StringBuffer mediaStatusXml = new StringBuffer(200); | |
| 881 | + mediaStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n"); | |
| 882 | + mediaStatusXml.append("<Response>\r\n"); | |
| 883 | + mediaStatusXml.append("<CmdType>Broadcast</CmdType>\r\n"); | |
| 884 | + mediaStatusXml.append("<SN>" + sn + "</SN>\r\n"); | |
| 885 | + mediaStatusXml.append("<DeviceID>" + deviceChannel.getChannelId() + "</DeviceID>\r\n"); | |
| 886 | + mediaStatusXml.append("<Result>" + (result?"OK":"ERROR") + "</Result>\r\n"); | |
| 887 | + mediaStatusXml.append("</Response>\r\n"); | |
| 888 | + | |
| 889 | + CallIdHeader callIdHeader = sipSender.getNewCallIdHeader(platform.getDeviceIp(), platform.getTransport()); | |
| 890 | + | |
| 891 | + SIPRequest messageRequest = (SIPRequest)headerProviderPlatformProvider.createMessageRequest(platform, mediaStatusXml.toString(), | |
| 892 | + SipUtils.getNewFromTag(), SipUtils.getNewViaTag(), callIdHeader); | |
| 893 | + | |
| 894 | + sipSender.transmitRequest(platform.getDeviceIp(),messageRequest, errorEvent, okEvent); | |
| 895 | + } | |
| 896 | + | |
| 897 | + @Override | |
| 898 | + public void broadcastInviteCmd(ParentPlatform platform, String channelId, MediaServerItem mediaServerItem, | |
| 899 | + SSRCInfo ssrcInfo, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, | |
| 900 | + SipSubscribe.Event errorEvent) throws ParseException, SipException, InvalidArgumentException { | |
| 901 | + String stream = ssrcInfo.getStream(); | |
| 902 | + | |
| 903 | + if (platform == null) { | |
| 904 | + return; | |
| 905 | + } | |
| 906 | + | |
| 907 | + logger.info("{} 分配的ZLM为: {} [{}:{}]", stream, mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort()); | |
| 908 | + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId()); | |
| 909 | + subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, HookParam hookParam) -> { | |
| 910 | + if (event != null) { | |
| 911 | + event.response(mediaServerItemInUse, hookParam); | |
| 912 | + subscribe.removeSubscribe(hookSubscribe); | |
| 913 | + } | |
| 914 | + }); | |
| 915 | + String sdpIp = mediaServerItem.getSdpIp(); | |
| 916 | + | |
| 917 | + StringBuffer content = new StringBuffer(200); | |
| 918 | + content.append("v=0\r\n"); | |
| 919 | + content.append("o=" + channelId + " 0 0 IN IP4 " + sdpIp + "\r\n"); | |
| 920 | + content.append("s=Play\r\n"); | |
| 921 | + content.append("c=IN IP4 " + sdpIp + "\r\n"); | |
| 922 | + content.append("t=0 0\r\n"); | |
| 923 | + | |
| 924 | + if ("TCP-PASSIVE".equalsIgnoreCase(userSetting.getBroadcastForPlatform())) { | |
| 925 | + content.append("m=audio " + ssrcInfo.getPort() + " TCP/RTP/AVP 8 96\r\n"); | |
| 926 | + } else if ("TCP-ACTIVE".equalsIgnoreCase(userSetting.getBroadcastForPlatform())) { | |
| 927 | + content.append("m=audio " + ssrcInfo.getPort() + " TCP/RTP/AVP 8 96\r\n"); | |
| 928 | + } else if ("UDP".equalsIgnoreCase(userSetting.getBroadcastForPlatform())) { | |
| 929 | + content.append("m=audio " + ssrcInfo.getPort() + " RTP/AVP 8 96\r\n"); | |
| 930 | + } | |
| 931 | + | |
| 932 | + content.append("a=recvonly\r\n"); | |
| 933 | + content.append("a=rtpmap:8 PCMA/8000\r\n"); | |
| 934 | + content.append("a=rtpmap:96 PS/90000\r\n"); | |
| 935 | + if ("TCP-PASSIVE".equalsIgnoreCase(userSetting.getBroadcastForPlatform())) { | |
| 936 | + content.append("a=setup:passive\r\n"); | |
| 937 | + content.append("a=connection:new\r\n"); | |
| 938 | + }else if ("TCP-ACTIVE".equalsIgnoreCase(userSetting.getBroadcastForPlatform())) { | |
| 939 | + content.append("a=setup:active\r\n"); | |
| 940 | + content.append("a=connection:new\r\n"); | |
| 941 | + } | |
| 942 | + | |
| 943 | + content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc | |
| 944 | + CallIdHeader callIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(platform.getDeviceIp()), platform.getTransport()); | |
| 945 | + | |
| 946 | + Request request = headerProviderPlatformProvider.createInviteRequest(platform, channelId, | |
| 947 | + content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), ssrcInfo.getSsrc(), | |
| 948 | + callIdHeader); | |
| 949 | + sipSender.transmitRequest(sipLayer.getLocalIp(platform.getDeviceIp()), request, (e -> { | |
| 950 | + streamSession.remove(platform.getServerGBId(), channelId, ssrcInfo.getStream()); | |
| 951 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | |
| 952 | + subscribe.removeSubscribe(hookSubscribe); | |
| 953 | + errorEvent.response(e); | |
| 954 | + }), e -> { | |
| 955 | + ResponseEvent responseEvent = (ResponseEvent) e.event; | |
| 956 | + SIPResponse response = (SIPResponse) responseEvent.getResponse(); | |
| 957 | + streamSession.put(platform.getServerGBId(), channelId, callIdHeader.getCallId(), stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response, InviteSessionType.BROADCAST); | |
| 958 | + okEvent.response(e); | |
| 959 | + }); | |
| 835 | 960 | } |
| 836 | 961 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
| ... | ... | @@ -82,6 +82,7 @@ public abstract class SIPRequestProcessorParent { |
| 82 | 82 | return responseAck(sipRequest, statusCode, msg, null); |
| 83 | 83 | } |
| 84 | 84 | |
| 85 | + | |
| 85 | 86 | public SIPResponse responseAck(SIPRequest sipRequest, int statusCode, String msg, ResponseAckExtraParam responseAckExtraParam) throws SipException, InvalidArgumentException, ParseException { |
| 86 | 87 | if (sipRequest.getToHeader().getTag() == null) { |
| 87 | 88 | sipRequest.getToHeader().setTag(SipUtils.getNewTag()); |
| ... | ... | @@ -124,6 +125,8 @@ public abstract class SIPRequestProcessorParent { |
| 124 | 125 | return response; |
| 125 | 126 | } |
| 126 | 127 | |
| 128 | + | |
| 129 | + | |
| 127 | 130 | /** |
| 128 | 131 | * 回复带sdp的200 |
| 129 | 132 | */ |
| ... | ... | @@ -141,7 +144,10 @@ public abstract class SIPRequestProcessorParent { |
| 141 | 144 | responseAckExtraParam.content = sdp; |
| 142 | 145 | responseAckExtraParam.sipURI = sipURI; |
| 143 | 146 | |
| 144 | - return responseAck(request, Response.OK, null, responseAckExtraParam); | |
| 147 | + SIPResponse sipResponse = responseAck(request, Response.OK, null, responseAckExtraParam); | |
| 148 | + | |
| 149 | + | |
| 150 | + return sipResponse; | |
| 145 | 151 | } |
| 146 | 152 | |
| 147 | 153 | /** |
| ... | ... | @@ -174,7 +180,8 @@ public abstract class SIPRequestProcessorParent { |
| 174 | 180 | reader.setEncoding(charset); |
| 175 | 181 | // 对海康出现的未转义字符做处理。 |
| 176 | 182 | String[] destStrArray = new String[]{"<",">","&","'","""}; |
| 177 | - char despChar = '&'; // 或许可扩展兼容其他字符 | |
| 183 | + // 或许可扩展兼容其他字符 | |
| 184 | + char despChar = '&'; | |
| 178 | 185 | byte destBye = (byte) despChar; |
| 179 | 186 | List<Byte> result = new ArrayList<>(); |
| 180 | 187 | byte[] rawContent = request.getRawContent(); |
| ... | ... | @@ -220,4 +227,5 @@ public abstract class SIPRequestProcessorParent { |
| 220 | 227 | return xml.getRootElement(); |
| 221 | 228 | } |
| 222 | 229 | |
| 230 | + | |
| 223 | 231 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
| 1 | 1 | package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; |
| 2 | 2 | |
| 3 | -import com.alibaba.fastjson2.JSON; | |
| 4 | 3 | import com.alibaba.fastjson2.JSONObject; |
| 5 | 4 | import com.genersoft.iot.vmp.conf.DynamicTask; |
| 6 | 5 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 7 | -import com.genersoft.iot.vmp.gb28181.bean.InviteStreamType; | |
| 6 | +import com.genersoft.iot.vmp.gb28181.bean.Device; | |
| 8 | 7 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| 9 | 8 | import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; |
| 10 | 9 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
| 11 | -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; | |
| 12 | -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; | |
| 13 | 10 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; |
| 14 | 11 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
| 15 | 12 | import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; |
| 16 | 13 | import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; |
| 17 | 14 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 15 | +import com.genersoft.iot.vmp.service.IDeviceService; | |
| 18 | 16 | import com.genersoft.iot.vmp.service.IMediaServerService; |
| 19 | -import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; | |
| 17 | +import com.genersoft.iot.vmp.service.IPlayService; | |
| 20 | 18 | import com.genersoft.iot.vmp.service.bean.RequestPushStreamMsg; |
| 21 | 19 | import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener; |
| 22 | 20 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| ... | ... | @@ -27,25 +25,23 @@ import org.springframework.beans.factory.InitializingBean; |
| 27 | 25 | import org.springframework.beans.factory.annotation.Autowired; |
| 28 | 26 | import org.springframework.stereotype.Component; |
| 29 | 27 | |
| 30 | -import javax.sip.InvalidArgumentException; | |
| 31 | 28 | import javax.sip.RequestEvent; |
| 32 | -import javax.sip.SipException; | |
| 33 | 29 | import javax.sip.address.SipURI; |
| 34 | 30 | import javax.sip.header.CallIdHeader; |
| 35 | 31 | import javax.sip.header.FromHeader; |
| 36 | 32 | import javax.sip.header.HeaderAddress; |
| 37 | 33 | import javax.sip.header.ToHeader; |
| 38 | -import java.text.ParseException; | |
| 39 | 34 | import java.util.HashMap; |
| 40 | 35 | import java.util.Map; |
| 41 | 36 | |
| 42 | 37 | /** |
| 43 | 38 | * SIP命令类型: ACK请求 |
| 39 | + * @author lin | |
| 44 | 40 | */ |
| 45 | 41 | @Component |
| 46 | 42 | public class AckRequestProcessor extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor { |
| 47 | 43 | |
| 48 | - private Logger logger = LoggerFactory.getLogger(AckRequestProcessor.class); | |
| 44 | + private final Logger logger = LoggerFactory.getLogger(AckRequestProcessor.class); | |
| 49 | 45 | private final String method = "ACK"; |
| 50 | 46 | |
| 51 | 47 | @Autowired |
| ... | ... | @@ -67,6 +63,9 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In |
| 67 | 63 | private IVideoManagerStorage storager; |
| 68 | 64 | |
| 69 | 65 | @Autowired |
| 66 | + private IDeviceService deviceService; | |
| 67 | + | |
| 68 | + @Autowired | |
| 70 | 69 | private ZLMServerFactory zlmServerFactory; |
| 71 | 70 | |
| 72 | 71 | @Autowired |
| ... | ... | @@ -76,112 +75,125 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In |
| 76 | 75 | private IMediaServerService mediaServerService; |
| 77 | 76 | |
| 78 | 77 | @Autowired |
| 79 | - private ZlmHttpHookSubscribe subscribe; | |
| 80 | - | |
| 81 | - @Autowired | |
| 82 | 78 | private DynamicTask dynamicTask; |
| 83 | 79 | |
| 84 | 80 | @Autowired |
| 85 | - private ISIPCommander cmder; | |
| 86 | - | |
| 87 | - @Autowired | |
| 88 | - private ISIPCommanderForPlatform commanderForPlatform; | |
| 81 | + private RedisGbPlayMsgListener redisGbPlayMsgListener; | |
| 89 | 82 | |
| 90 | 83 | @Autowired |
| 91 | - private RedisGbPlayMsgListener redisGbPlayMsgListener; | |
| 84 | + private IPlayService playService; | |
| 92 | 85 | |
| 93 | 86 | |
| 94 | 87 | /** |
| 95 | 88 | * 处理 ACK请求 |
| 96 | - * | |
| 97 | - * @param evt | |
| 98 | 89 | */ |
| 99 | 90 | @Override |
| 100 | 91 | public void process(RequestEvent evt) { |
| 101 | 92 | CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME); |
| 102 | - | |
| 103 | - String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); | |
| 104 | - logger.info("[收到ACK]: platformGbId->{}", platformGbId); | |
| 105 | - ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformGbId); | |
| 106 | - // 取消设置的超时任务 | |
| 107 | 93 | dynamicTask.stop(callIdHeader.getCallId()); |
| 108 | - String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); | |
| 109 | - SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId()); | |
| 94 | + String fromUserId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); | |
| 95 | + String toUserId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); | |
| 96 | + logger.info("[收到ACK]: 来自->{}", fromUserId); | |
| 97 | + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, null, callIdHeader.getCallId()); | |
| 110 | 98 | if (sendRtpItem == null) { |
| 111 | - logger.warn("[收到ACK]:未找到通道({})的推流信息", channelId); | |
| 99 | + logger.warn("[收到ACK]:未找到来自{},目标为({})的推流信息",fromUserId, toUserId); | |
| 112 | 100 | return; |
| 113 | 101 | } |
| 114 | 102 | // tcp主动时,此时是级联下级平台,在回复200ok时,本地已经请求zlm开启监听,跳过下面步骤 |
| 115 | 103 | if (sendRtpItem.isTcpActive()) { |
| 116 | - logger.info("收到ACK,rtp/{} TCP主动方式后续处理", sendRtpItem.getStreamId()); | |
| 104 | + logger.info("收到ACK,rtp/{} TCP主动方式后续处理", sendRtpItem.getStream()); | |
| 117 | 105 | return; |
| 118 | 106 | } |
| 119 | - String is_Udp = sendRtpItem.isTcp() ? "0" : "1"; | |
| 120 | 107 | MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); |
| 121 | 108 | logger.info("收到ACK,rtp/{}开始向上级推流, 目标={}:{},SSRC={}, 协议:{}", |
| 122 | - sendRtpItem.getStreamId(), | |
| 109 | + sendRtpItem.getStream(), | |
| 123 | 110 | sendRtpItem.getIp(), |
| 124 | 111 | sendRtpItem.getPort(), |
| 125 | 112 | sendRtpItem.getSsrc(), |
| 126 | 113 | sendRtpItem.isTcp()?(sendRtpItem.isTcpActive()?"TCP主动":"TCP被动"):"UDP" |
| 127 | 114 | ); |
| 115 | + ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(fromUserId); | |
| 116 | + | |
| 117 | + if (parentPlatform != null) { | |
| 118 | + Map<String, Object> param = getSendRtpParam(sendRtpItem); | |
| 119 | + if (mediaInfo == null) { | |
| 120 | + RequestPushStreamMsg requestPushStreamMsg = RequestPushStreamMsg.getInstance( | |
| 121 | + sendRtpItem.getMediaServerId(), sendRtpItem.getApp(), sendRtpItem.getStream(), | |
| 122 | + sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isTcp(), | |
| 123 | + sendRtpItem.getLocalPort(), sendRtpItem.getPt(), sendRtpItem.isUsePs(), sendRtpItem.isOnlyAudio()); | |
| 124 | + redisGbPlayMsgListener.sendMsgForStartSendRtpStream(sendRtpItem.getServerId(), requestPushStreamMsg, json -> { | |
| 125 | + playService.startSendRtpStreamHand(sendRtpItem, parentPlatform, json, param, callIdHeader); | |
| 126 | + }); | |
| 127 | + } else { | |
| 128 | + JSONObject startSendRtpStreamResult = sendRtp(sendRtpItem, mediaInfo, param); | |
| 129 | + if (startSendRtpStreamResult != null) { | |
| 130 | + playService.startSendRtpStreamHand(sendRtpItem, parentPlatform, startSendRtpStreamResult, param, callIdHeader); | |
| 131 | + } | |
| 132 | + } | |
| 133 | + }else { | |
| 134 | + Device device = deviceService.getDevice(fromUserId); | |
| 135 | + if (device == null) { | |
| 136 | + logger.warn("[收到ACK]:来自{},目标为({})的推流信息为找到流体服务[{}]信息",fromUserId, toUserId, sendRtpItem.getMediaServerId()); | |
| 137 | + return; | |
| 138 | + } | |
| 139 | + // 设置为收到ACK后发送语音的设备已经在发送200OK开始发流了 | |
| 140 | + if (!device.isBroadcastPushAfterAck()) { | |
| 141 | + return; | |
| 142 | + } | |
| 143 | + if (mediaInfo == null) { | |
| 144 | + logger.warn("[收到ACK]:来自{},目标为({})的推流信息为找到流体服务[{}]信息",fromUserId, toUserId, sendRtpItem.getMediaServerId()); | |
| 145 | + return; | |
| 146 | + } | |
| 147 | + Map<String, Object> param = getSendRtpParam(sendRtpItem); | |
| 148 | + JSONObject startSendRtpStreamResult = sendRtp(sendRtpItem, mediaInfo, param); | |
| 149 | + if (startSendRtpStreamResult != null) { | |
| 150 | + playService.startSendRtpStreamHand(sendRtpItem, device, startSendRtpStreamResult, param, callIdHeader); | |
| 151 | + } | |
| 152 | + } | |
| 153 | + } | |
| 154 | + | |
| 155 | + private Map<String, Object> getSendRtpParam(SendRtpItem sendRtpItem) { | |
| 156 | + String isUdp = sendRtpItem.isTcp() ? "0" : "1"; | |
| 128 | 157 | Map<String, Object> param = new HashMap<>(12); |
| 129 | 158 | param.put("vhost","__defaultVhost__"); |
| 130 | 159 | param.put("app",sendRtpItem.getApp()); |
| 131 | - param.put("stream",sendRtpItem.getStreamId()); | |
| 160 | + param.put("stream",sendRtpItem.getStream()); | |
| 132 | 161 | param.put("ssrc", sendRtpItem.getSsrc()); |
| 133 | 162 | param.put("dst_url",sendRtpItem.getIp()); |
| 134 | 163 | param.put("dst_port", sendRtpItem.getPort()); |
| 135 | - param.put("is_udp", is_Udp); | |
| 136 | 164 | param.put("src_port", sendRtpItem.getLocalPort()); |
| 137 | 165 | param.put("pt", sendRtpItem.getPt()); |
| 138 | 166 | param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0"); |
| 139 | 167 | param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0"); |
| 168 | + param.put("is_udp", isUdp); | |
| 140 | 169 | if (!sendRtpItem.isTcp()) { |
| 141 | - // 开启rtcp保活 | |
| 170 | + // udp模式下开启rtcp保活 | |
| 142 | 171 | param.put("udp_rtcp_timeout", sendRtpItem.isRtcp()? "1":"0"); |
| 143 | 172 | } |
| 144 | - if (mediaInfo == null) { | |
| 145 | - RequestPushStreamMsg requestPushStreamMsg = RequestPushStreamMsg.getInstance( | |
| 146 | - sendRtpItem.getMediaServerId(), sendRtpItem.getApp(), sendRtpItem.getStreamId(), | |
| 147 | - sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isTcp(), | |
| 148 | - sendRtpItem.getLocalPort(), sendRtpItem.getPt(), sendRtpItem.isUsePs(), sendRtpItem.isOnlyAudio()); | |
| 149 | - redisGbPlayMsgListener.sendMsgForStartSendRtpStream(sendRtpItem.getServerId(), requestPushStreamMsg, jsonObject->{ | |
| 150 | - startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, jsonObject, param, callIdHeader); | |
| 151 | - }); | |
| 152 | - }else { | |
| 153 | - JSONObject startSendRtpStreamResult = zlmServerFactory.startSendRtpStream(mediaInfo, param); | |
| 154 | - if (startSendRtpStreamResult != null) { | |
| 155 | - startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, startSendRtpStreamResult, param, callIdHeader); | |
| 156 | - } | |
| 157 | - } | |
| 173 | + return param; | |
| 158 | 174 | } |
| 159 | - private void startSendRtpStreamHand(RequestEvent evt, SendRtpItem sendRtpItem, ParentPlatform parentPlatform, | |
| 160 | - JSONObject jsonObject, Map<String, Object> param, CallIdHeader callIdHeader) { | |
| 161 | - if (jsonObject == null) { | |
| 162 | - logger.error("RTP推流失败: 请检查ZLM服务"); | |
| 163 | - } else if (jsonObject.getInteger("code") == 0) { | |
| 164 | - logger.info("调用ZLM推流接口, 结果: {}", jsonObject); | |
| 165 | - logger.info("RTP推流成功[ {}/{} ],{}->{}:{}, " ,param.get("app"), param.get("stream"), jsonObject.getString("local_port"), param.get("dst_url"), param.get("dst_port")); | |
| 166 | - if (sendRtpItem.getPlayType() == InviteStreamType.PUSH) { | |
| 167 | - MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, sendRtpItem.getApp(), sendRtpItem.getStreamId(), | |
| 168 | - sendRtpItem.getChannelId(), parentPlatform.getServerGBId(), parentPlatform.getName(), userSetting.getServerId(), | |
| 169 | - sendRtpItem.getMediaServerId()); | |
| 170 | - messageForPushChannel.setPlatFormIndex(parentPlatform.getId()); | |
| 171 | - redisCatchStorage.sendPlatformStartPlayMsg(messageForPushChannel); | |
| 175 | + | |
| 176 | + private JSONObject sendRtp(SendRtpItem sendRtpItem, MediaServerItem mediaInfo, Map<String, Object> param){ | |
| 177 | + JSONObject startSendRtpStreamResult = null; | |
| 178 | + if (sendRtpItem.getLocalPort() != 0) { | |
| 179 | + if (sendRtpItem.isTcpActive()) { | |
| 180 | + startSendRtpStreamResult = zlmServerFactory.startSendRtpPassive(mediaInfo, param); | |
| 181 | + }else { | |
| 182 | + param.put("dst_url", sendRtpItem.getIp()); | |
| 183 | + param.put("dst_port", sendRtpItem.getPort()); | |
| 184 | + startSendRtpStreamResult = zlmServerFactory.startSendRtpStream(mediaInfo, param); | |
| 172 | 185 | } |
| 173 | - } else { | |
| 174 | - logger.error("RTP推流失败: {}, 参数:{}",jsonObject.getString("msg"), JSON.toJSONString(param)); | |
| 175 | - if (sendRtpItem.isOnlyAudio()) { | |
| 176 | - // TODO 可能是语音对讲 | |
| 186 | + }else { | |
| 187 | + if (sendRtpItem.isTcpActive()) { | |
| 188 | + startSendRtpStreamResult = zlmServerFactory.startSendRtpPassive(mediaInfo, param); | |
| 177 | 189 | }else { |
| 178 | - // 向上级平台 | |
| 179 | - try { | |
| 180 | - commanderForPlatform.streamByeCmd(parentPlatform, callIdHeader.getCallId()); | |
| 181 | - } catch (SipException | InvalidArgumentException | ParseException e) { | |
| 182 | - logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage()); | |
| 183 | - } | |
| 190 | + param.put("dst_url", sendRtpItem.getIp()); | |
| 191 | + param.put("dst_port", sendRtpItem.getPort()); | |
| 192 | + startSendRtpStreamResult = zlmServerFactory.startSendRtpStream(mediaInfo, param); | |
| 184 | 193 | } |
| 185 | 194 | } |
| 195 | + return startSendRtpStreamResult; | |
| 196 | + | |
| 186 | 197 | } |
| 198 | + | |
| 187 | 199 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
| ... | ... | @@ -5,10 +5,12 @@ import com.genersoft.iot.vmp.common.InviteSessionType; |
| 5 | 5 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 6 | 6 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; |
| 7 | 7 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 8 | +import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; | |
| 8 | 9 | import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; |
| 9 | 10 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 10 | 11 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
| 11 | 12 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; |
| 13 | +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; | |
| 12 | 14 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; |
| 13 | 15 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
| 14 | 16 | import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; |
| ... | ... | @@ -46,6 +48,9 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In |
| 46 | 48 | private ISIPCommander cmder; |
| 47 | 49 | |
| 48 | 50 | @Autowired |
| 51 | + private ISIPCommanderForPlatform commanderForPlatform; | |
| 52 | + | |
| 53 | + @Autowired | |
| 49 | 54 | private IRedisCatchStorage redisCatchStorage; |
| 50 | 55 | |
| 51 | 56 | @Autowired |
| ... | ... | @@ -58,6 +63,9 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In |
| 58 | 63 | private IDeviceService deviceService; |
| 59 | 64 | |
| 60 | 65 | @Autowired |
| 66 | + private AudioBroadcastManager audioBroadcastManager; | |
| 67 | + | |
| 68 | + @Autowired | |
| 61 | 69 | private IDeviceChannelService channelService; |
| 62 | 70 | |
| 63 | 71 | @Autowired |
| ... | ... | @@ -79,6 +87,9 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In |
| 79 | 87 | private VideoStreamSessionManager streamSession; |
| 80 | 88 | |
| 81 | 89 | @Autowired |
| 90 | + private IPlayService playService; | |
| 91 | + | |
| 92 | + @Autowired | |
| 82 | 93 | private UserSetting userSetting; |
| 83 | 94 | |
| 84 | 95 | @Override |
| ... | ... | @@ -100,18 +111,19 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In |
| 100 | 111 | logger.error("[回复BYE信息失败],{}", e.getMessage()); |
| 101 | 112 | } |
| 102 | 113 | CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME); |
| 103 | - | |
| 104 | 114 | SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, null, callIdHeader.getCallId()); |
| 105 | 115 | |
| 116 | + // 收流端发送的停止 | |
| 106 | 117 | if (sendRtpItem != null){ |
| 107 | - logger.info("[收到bye] 来自平台{}, 停止通道:{}", sendRtpItem.getPlatformId(), sendRtpItem.getChannelId()); | |
| 108 | - String streamId = sendRtpItem.getStreamId(); | |
| 118 | + logger.info("[收到bye] 来自{},停止通道:{}, 类型: {}", sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(), sendRtpItem.getPlayType()); | |
| 119 | + | |
| 120 | + String streamId = sendRtpItem.getStream(); | |
| 109 | 121 | Map<String, Object> param = new HashMap<>(); |
| 110 | 122 | param.put("vhost","__defaultVhost__"); |
| 111 | 123 | param.put("app",sendRtpItem.getApp()); |
| 112 | 124 | param.put("stream",streamId); |
| 113 | 125 | param.put("ssrc",sendRtpItem.getSsrc()); |
| 114 | - logger.info("[收到bye] 停止向上级推流:{}", streamId); | |
| 126 | + logger.info("[收到bye] 停止推流:{}", streamId); | |
| 115 | 127 | MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); |
| 116 | 128 | redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(), |
| 117 | 129 | callIdHeader.getCallId(), null); |
| ... | ... | @@ -123,7 +135,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In |
| 123 | 135 | ParentPlatform platform = platformService.queryPlatformByServerGBId(sendRtpItem.getPlatformId()); |
| 124 | 136 | if (platform != null) { |
| 125 | 137 | MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, |
| 126 | - sendRtpItem.getApp(), sendRtpItem.getStreamId(), sendRtpItem.getChannelId(), | |
| 138 | + sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getChannelId(), | |
| 127 | 139 | sendRtpItem.getPlatformId(), platform.getName(), userSetting.getServerId(), sendRtpItem.getMediaServerId()); |
| 128 | 140 | messageForPushChannel.setPlatFormIndex(platform.getId()); |
| 129 | 141 | redisCatchStorage.sendPlatformStopPlayMsg(messageForPushChannel); |
| ... | ... | @@ -132,6 +144,13 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In |
| 132 | 144 | } |
| 133 | 145 | } |
| 134 | 146 | |
| 147 | + AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); | |
| 148 | + if (audioBroadcastCatch != null && audioBroadcastCatch.getSipTransactionInfo().getCallId().equals(callIdHeader.getCallId())) { | |
| 149 | + // 来自上级平台的停止对讲 | |
| 150 | + logger.info("[停止对讲] 来自上级,平台:{}, 通道:{}", sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); | |
| 151 | + audioBroadcastManager.del(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); | |
| 152 | + } | |
| 153 | + | |
| 135 | 154 | int totalReaderCount = zlmServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId); |
| 136 | 155 | if (totalReaderCount <= 0) { |
| 137 | 156 | logger.info("[收到bye] {} 无其它观看者,通知设备停止推流", streamId); |
| ... | ... | @@ -149,7 +168,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In |
| 149 | 168 | } |
| 150 | 169 | } |
| 151 | 170 | } |
| 152 | - }else { | |
| 171 | + } | |
| 153 | 172 | |
| 154 | 173 | // 可能是设备发送的停止 |
| 155 | 174 | SsrcTransaction ssrcTransaction = streamSession.getSsrcTransactionByCallId(callIdHeader.getCallId()); |
| ... | ... | @@ -158,6 +177,23 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In |
| 158 | 177 | } |
| 159 | 178 | logger.info("[收到bye] 来自设备:{}, 通道已停止推流: {}", ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId()); |
| 160 | 179 | |
| 180 | + ParentPlatform platform = platformService.queryPlatformByServerGBId(ssrcTransaction.getDeviceId()); | |
| 181 | + if (platform != null ) { | |
| 182 | + if (ssrcTransaction.getType().equals(InviteSessionType.BROADCAST)) { | |
| 183 | + logger.info("[收到bye] 上级停止语音对讲,来自:{}, 通道已停止推流: {}", ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId()); | |
| 184 | + DeviceChannel channel = storager.queryChannelInParentPlatform(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId()); | |
| 185 | + if (channel == null) { | |
| 186 | + logger.info("[收到bye] 未找到通道,设备:{}, 通道:{}", ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId()); | |
| 187 | + return; | |
| 188 | + } | |
| 189 | + String mediaServerId = ssrcTransaction.getMediaServerId(); | |
| 190 | + platformService.stopBroadcast(platform, channel, ssrcTransaction.getStream(), false, | |
| 191 | + mediaServerService.getOne(mediaServerId)); | |
| 192 | + | |
| 193 | + playService.stopAudioBroadcast(channel.getDeviceId(), channel.getChannelId()); | |
| 194 | + } | |
| 195 | + | |
| 196 | + }else { | |
| 161 | 197 | Device device = deviceService.getDevice(ssrcTransaction.getDeviceId()); |
| 162 | 198 | if (device == null) { |
| 163 | 199 | logger.info("[收到bye] 未找到设备:{} ", ssrcTransaction.getDeviceId()); |
| ... | ... | @@ -182,6 +218,19 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In |
| 182 | 218 | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransaction.getSsrc()); |
| 183 | 219 | } |
| 184 | 220 | streamSession.removeByCallId(device.getDeviceId(), channel.getChannelId(), ssrcTransaction.getCallId()); |
| 221 | + if (ssrcTransaction.getType() == InviteSessionType.BROADCAST) { | |
| 222 | + // 查找来源的对讲设备,发送停止 | |
| 223 | + Device sourceDevice = storager.queryVideoDeviceByPlatformIdAndChannelId(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId()); | |
| 224 | + if (sourceDevice != null) { | |
| 225 | + playService.stopAudioBroadcast(sourceDevice.getDeviceId(), channel.getChannelId()); | |
| 226 | + } | |
| 227 | + } | |
| 228 | + AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(ssrcTransaction.getDeviceId(), channel.getChannelId()); | |
| 229 | + if (audioBroadcastCatch != null) { | |
| 230 | + // 来自上级平台的停止对讲 | |
| 231 | + logger.info("[停止对讲] 来自上级,平台:{}, 通道:{}", ssrcTransaction.getDeviceId(), channel.getChannelId()); | |
| 232 | + audioBroadcastManager.del(ssrcTransaction.getDeviceId(), channel.getChannelId()); | |
| 233 | + } | |
| 185 | 234 | } |
| 186 | 235 | } |
| 187 | 236 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
| ... | ... | @@ -2,14 +2,19 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; |
| 2 | 2 | |
| 3 | 3 | import com.alibaba.fastjson2.JSON; |
| 4 | 4 | import com.alibaba.fastjson2.JSONObject; |
| 5 | +import com.genersoft.iot.vmp.common.InviteSessionType; | |
| 5 | 6 | import com.genersoft.iot.vmp.common.StreamInfo; |
| 7 | +import com.genersoft.iot.vmp.common.VideoManagerConstants; | |
| 6 | 8 | import com.genersoft.iot.vmp.conf.DynamicTask; |
| 9 | +import com.genersoft.iot.vmp.conf.SipConfig; | |
| 7 | 10 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 8 | 11 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 12 | +import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; | |
| 9 | 13 | import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; |
| 14 | +import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | |
| 10 | 15 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
| 11 | 16 | import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; |
| 12 | -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; | |
| 17 | +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; | |
| 13 | 18 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; |
| 14 | 19 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
| 15 | 20 | import com.genersoft.iot.vmp.gb28181.utils.SipUtils; |
| ... | ... | @@ -65,13 +70,14 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 65 | 70 | private final String method = "INVITE"; |
| 66 | 71 | |
| 67 | 72 | @Autowired |
| 68 | - private SIPCommanderFroPlatform cmderFroPlatform; | |
| 73 | + private ISIPCommanderForPlatform cmderFroPlatform; | |
| 69 | 74 | |
| 70 | 75 | @Autowired |
| 71 | 76 | private IVideoManagerStorage storager; |
| 72 | 77 | |
| 73 | 78 | @Autowired |
| 74 | 79 | private IStreamPushService streamPushService; |
| 80 | + | |
| 75 | 81 | @Autowired |
| 76 | 82 | private IStreamProxyService streamProxyService; |
| 77 | 83 | |
| ... | ... | @@ -97,6 +103,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 97 | 103 | private SIPSender sipSender; |
| 98 | 104 | |
| 99 | 105 | @Autowired |
| 106 | + private AudioBroadcastManager audioBroadcastManager; | |
| 107 | + | |
| 108 | + @Autowired | |
| 100 | 109 | private ZLMServerFactory zlmServerFactory; |
| 101 | 110 | |
| 102 | 111 | @Autowired |
| ... | ... | @@ -114,10 +123,16 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 114 | 123 | @Autowired |
| 115 | 124 | private ZLMMediaListManager mediaListManager; |
| 116 | 125 | |
| 126 | + @Autowired | |
| 127 | + private SipConfig config; | |
| 128 | + | |
| 117 | 129 | |
| 118 | 130 | @Autowired |
| 119 | 131 | private RedisGbPlayMsgListener redisGbPlayMsgListener; |
| 120 | 132 | |
| 133 | + @Autowired | |
| 134 | + private VideoStreamSessionManager streamSession; | |
| 135 | + | |
| 121 | 136 | |
| 122 | 137 | @Override |
| 123 | 138 | public void afterPropertiesSet() throws Exception { |
| ... | ... | @@ -168,7 +183,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 168 | 183 | // 查询请求是否来自上级平台\设备 |
| 169 | 184 | ParentPlatform platform = storager.queryParentPlatByServerGBId(requesterId); |
| 170 | 185 | if (platform == null) { |
| 171 | - inviteFromDeviceHandle(request, requesterId); | |
| 186 | + inviteFromDeviceHandle(request, requesterId, channelId); | |
| 172 | 187 | |
| 173 | 188 | } else { |
| 174 | 189 | // 查询平台下是否有该通道 |
| ... | ... | @@ -178,7 +193,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 178 | 193 | |
| 179 | 194 | MediaServerItem mediaServerItem = null; |
| 180 | 195 | StreamPushItem streamPushItem = null; |
| 181 | - StreamProxyItem proxyByAppAndStream =null; | |
| 196 | + StreamProxyItem proxyByAppAndStream = null; | |
| 182 | 197 | // 不是通道可能是直播流 |
| 183 | 198 | if (channel != null && gbStream == null) { |
| 184 | 199 | // 通道存在,发100,TRYING |
| ... | ... | @@ -221,7 +236,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 221 | 236 | } |
| 222 | 237 | return; |
| 223 | 238 | } |
| 224 | - }else if("proxy".equals(gbStream.getStreamType())){ | |
| 239 | + } else if ("proxy".equals(gbStream.getStreamType())) { | |
| 225 | 240 | proxyByAppAndStream = streamProxyService.getStreamProxyByAppAndStream(gbStream.getApp(), gbStream.getStream()); |
| 226 | 241 | if (proxyByAppAndStream == null) { |
| 227 | 242 | logger.info("[ app={}, stream={} ]找不到zlm {},返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId); |
| ... | ... | @@ -353,10 +368,10 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 353 | 368 | if (mediaTransmissionTCP) { |
| 354 | 369 | if (tcpActive) { |
| 355 | 370 | streamTypeStr = "TCP-ACTIVE"; |
| 356 | - }else { | |
| 371 | + } else { | |
| 357 | 372 | streamTypeStr = "TCP-PASSIVE"; |
| 358 | 373 | } |
| 359 | - }else { | |
| 374 | + } else { | |
| 360 | 375 | streamTypeStr = "UDP"; |
| 361 | 376 | } |
| 362 | 377 | logger.info("[上级Invite] {}, 平台:{}, 通道:{}, 收流地址:{}:{},收流方式:{}, ssrc:{}", sessionName, username, channelId, addressStr, port, streamTypeStr, ssrc); |
| ... | ... | @@ -440,7 +455,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 440 | 455 | Map<String, Object> param = new HashMap<>(12); |
| 441 | 456 | param.put("vhost","__defaultVhost__"); |
| 442 | 457 | param.put("app",sendRtpItem.getApp()); |
| 443 | - param.put("stream",sendRtpItem.getStreamId()); | |
| 458 | + param.put("stream",sendRtpItem.getStream()); | |
| 444 | 459 | param.put("ssrc", sendRtpItem.getSsrc()); |
| 445 | 460 | if (!sendRtpItem.isTcpActive()) { |
| 446 | 461 | param.put("dst_url",sendRtpItem.getIp()); |
| ... | ... | @@ -456,7 +471,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 456 | 471 | // 开启rtcp保活 |
| 457 | 472 | param.put("udp_rtcp_timeout", sendRtpItem.isRtcp()? "1":"0"); |
| 458 | 473 | } |
| 459 | - JSONObject startSendRtpStreamResult = zlmServerFactory.startSendRtpStreamForPassive(mediaInfo, param); | |
| 474 | + JSONObject startSendRtpStreamResult = zlmServerFactory.startSendRtpPassive(mediaInfo, param); | |
| 460 | 475 | if (startSendRtpStreamResult != null) { |
| 461 | 476 | startSendRtpStreamHand(evt, sendRtpItem, null, startSendRtpStreamResult, param, callIdHeader); |
| 462 | 477 | } |
| ... | ... | @@ -472,7 +487,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 472 | 487 | Response response = getMessageFactory().createResponse(statusCode, evt.getRequest()); |
| 473 | 488 | sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response); |
| 474 | 489 | } |
| 475 | - } catch (ParseException | SipException e) { | |
| 490 | + } catch (ParseException | SipException e) { | |
| 476 | 491 | logger.error("未处理的异常 ", e); |
| 477 | 492 | } |
| 478 | 493 | }); |
| ... | ... | @@ -482,20 +497,19 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 482 | 497 | String startTimeStr = DateUtil.urlFormatter.format(start); |
| 483 | 498 | String endTimeStr = DateUtil.urlFormatter.format(end); |
| 484 | 499 | String stream = device.getDeviceId() + "_" + channelId + "_" + startTimeStr + "_" + endTimeStr; |
| 485 | - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, stream, null, device.isSsrcCheck(), true, 0, false, device.getStreamModeForParam()); | |
| 486 | - sendRtpItem.setStreamId(ssrcInfo.getStream()); | |
| 500 | + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, stream, null, device.isSsrcCheck(), true, 0,false, false, device.getStreamModeForParam()); | |
| 487 | 501 | // 写入redis, 超时时回复 |
| 488 | 502 | redisCatchStorage.updateSendRTPSever(sendRtpItem); |
| 489 | 503 | playService.playBack(mediaServerItem, ssrcInfo, device.getDeviceId(), channelId, DateUtil.formatter.format(start), |
| 490 | 504 | DateUtil.formatter.format(end), |
| 491 | 505 | (code, msg, data) -> { |
| 492 | - if (code == InviteErrorCode.SUCCESS.getCode()){ | |
| 506 | + if (code == InviteErrorCode.SUCCESS.getCode()) { | |
| 493 | 507 | hookEvent.run(code, msg, data); |
| 494 | - }else if (code == InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode() || code == InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode()){ | |
| 508 | + } else if (code == InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode() || code == InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode()) { | |
| 495 | 509 | logger.info("[录像回放]超时, 用户:{}, 通道:{}", username, channelId); |
| 496 | 510 | redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null); |
| 497 | 511 | errorEvent.run(code, msg, data); |
| 498 | - }else { | |
| 512 | + } else { | |
| 499 | 513 | errorEvent.run(code, msg, data); |
| 500 | 514 | } |
| 501 | 515 | }); |
| ... | ... | @@ -512,8 +526,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 512 | 526 | } |
| 513 | 527 | |
| 514 | 528 | sendRtpItem.setPlayType(InviteStreamType.DOWNLOAD); |
| 515 | - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, null, device.isSsrcCheck(), true, 0, false, device.getStreamModeForParam()); | |
| 516 | - sendRtpItem.setStreamId(ssrcInfo.getStream()); | |
| 529 | + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, null, device.isSsrcCheck(), true, 0, false, false, device.getStreamModeForParam()); | |
| 530 | + sendRtpItem.setStream(ssrcInfo.getStream()); | |
| 517 | 531 | // 写入redis, 超时时回复 |
| 518 | 532 | redisCatchStorage.updateSendRTPSever(sendRtpItem); |
| 519 | 533 | playService.download(mediaServerItem, ssrcInfo, device.getDeviceId(), channelId, DateUtil.formatter.format(start), |
| ... | ... | @@ -532,7 +546,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 532 | 546 | } else { |
| 533 | 547 | sendRtpItem.setPlayType(InviteStreamType.PLAY); |
| 534 | 548 | String streamId = String.format("%s_%s", device.getDeviceId(), channelId); |
| 535 | - sendRtpItem.setStreamId(streamId); | |
| 549 | + sendRtpItem.setStream(streamId); | |
| 536 | 550 | redisCatchStorage.updateSendRTPSever(sendRtpItem); |
| 537 | 551 | SSRCInfo ssrcInfo = playService.play(mediaServerItem, device.getDeviceId(), channelId, ssrc, ((code, msg, data) -> { |
| 538 | 552 | if (code == InviteErrorCode.SUCCESS.getCode()) { |
| ... | ... | @@ -559,24 +573,24 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 559 | 573 | ssrc = gb28181Sdp.getSsrc(); |
| 560 | 574 | } |
| 561 | 575 | |
| 562 | - if("push".equals(gbStream.getStreamType())) { | |
| 576 | + if ("push".equals(gbStream.getStreamType())) { | |
| 563 | 577 | if (streamPushItem != null && streamPushItem.isPushIng()) { |
| 564 | 578 | // 推流状态 |
| 565 | 579 | pushStream(evt, request, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, |
| 566 | 580 | mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); |
| 567 | 581 | } else { |
| 568 | 582 | // 未推流 拉起 |
| 569 | - notifyStreamOnline(evt, request,gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, | |
| 583 | + notifyStreamOnline(evt, request, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, | |
| 570 | 584 | mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); |
| 571 | 585 | } |
| 572 | - }else if ("proxy".equals(gbStream.getStreamType())){ | |
| 586 | + } else if ("proxy".equals(gbStream.getStreamType())) { | |
| 573 | 587 | if (null != proxyByAppAndStream) { |
| 574 | - if(proxyByAppAndStream.isStatus()){ | |
| 575 | - pushProxyStream(evt, request, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive, | |
| 588 | + if (proxyByAppAndStream.isStatus()) { | |
| 589 | + pushProxyStream(evt, request, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive, | |
| 576 | 590 | mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); |
| 577 | - }else{ | |
| 591 | + } else { | |
| 578 | 592 | //开启代理拉流 |
| 579 | - notifyStreamOnline(evt, request,gbStream, null, platform, callIdHeader, mediaServerItem, port, tcpActive, | |
| 593 | + notifyStreamOnline(evt, request, gbStream, null, platform, callIdHeader, mediaServerItem, port, tcpActive, | |
| 580 | 594 | mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); |
| 581 | 595 | } |
| 582 | 596 | } |
| ... | ... | @@ -617,33 +631,34 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 617 | 631 | SendRtpItem sendRtpItem = zlmServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, |
| 618 | 632 | gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp()); |
| 619 | 633 | |
| 620 | - if (sendRtpItem == null) { | |
| 621 | - logger.warn("服务器端口资源不足"); | |
| 622 | - try { | |
| 623 | - responseAck(request, Response.BUSY_HERE); | |
| 624 | - } catch (SipException | InvalidArgumentException | ParseException e) { | |
| 625 | - logger.error("[命令发送失败] invite 服务器端口资源不足: {}", e.getMessage()); | |
| 626 | - } | |
| 627 | - return; | |
| 628 | - } | |
| 629 | - if (tcpActive != null) { | |
| 630 | - sendRtpItem.setTcpActive(tcpActive); | |
| 631 | - } | |
| 632 | - sendRtpItem.setPlayType(InviteStreamType.PUSH); | |
| 633 | - // 写入redis, 超时时回复 | |
| 634 | - sendRtpItem.setStatus(1); | |
| 635 | - sendRtpItem.setCallId(callIdHeader.getCallId()); | |
| 636 | - sendRtpItem.setFromTag(request.getFromTag()); | |
| 637 | - | |
| 638 | - SIPResponse response = sendStreamAck(mediaServerItem, request, sendRtpItem, platform, evt); | |
| 639 | - if (response != null) { | |
| 640 | - sendRtpItem.setToTag(response.getToTag()); | |
| 634 | + if (sendRtpItem == null) { | |
| 635 | + logger.warn("服务器端口资源不足"); | |
| 636 | + try { | |
| 637 | + responseAck(request, Response.BUSY_HERE); | |
| 638 | + } catch (SipException | InvalidArgumentException | ParseException e) { | |
| 639 | + logger.error("[命令发送失败] invite 服务器端口资源不足: {}", e.getMessage()); | |
| 641 | 640 | } |
| 642 | - redisCatchStorage.updateSendRTPSever(sendRtpItem); | |
| 641 | + return; | |
| 642 | + } | |
| 643 | + if (tcpActive != null) { | |
| 644 | + sendRtpItem.setTcpActive(tcpActive); | |
| 645 | + } | |
| 646 | + sendRtpItem.setPlayType(InviteStreamType.PUSH); | |
| 647 | + // 写入redis, 超时时回复 | |
| 648 | + sendRtpItem.setStatus(1); | |
| 649 | + sendRtpItem.setCallId(callIdHeader.getCallId()); | |
| 650 | + sendRtpItem.setFromTag(request.getFromTag()); | |
| 651 | + | |
| 652 | + SIPResponse response = sendStreamAck(mediaServerItem, request, sendRtpItem, platform, evt); | |
| 653 | + if (response != null) { | |
| 654 | + sendRtpItem.setToTag(response.getToTag()); | |
| 655 | + } | |
| 656 | + redisCatchStorage.updateSendRTPSever(sendRtpItem); | |
| 643 | 657 | |
| 644 | 658 | } |
| 645 | 659 | |
| 646 | 660 | } |
| 661 | + | |
| 647 | 662 | private void pushStream(RequestEvent evt, SIPRequest request, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform, |
| 648 | 663 | CallIdHeader callIdHeader, MediaServerItem mediaServerItem, |
| 649 | 664 | int port, Boolean tcpActive, boolean mediaTransmissionTCP, |
| ... | ... | @@ -678,12 +693,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 678 | 693 | if (response != null) { |
| 679 | 694 | sendRtpItem.setToTag(response.getToTag()); |
| 680 | 695 | } |
| 681 | - | |
| 682 | 696 | redisCatchStorage.updateSendRTPSever(sendRtpItem); |
| 683 | 697 | |
| 684 | 698 | } else { |
| 685 | 699 | // 不在线 拉起 |
| 686 | - notifyStreamOnline(evt, request,gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, | |
| 700 | + notifyStreamOnline(evt, request, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, | |
| 687 | 701 | mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); |
| 688 | 702 | } |
| 689 | 703 | |
| ... | ... | @@ -693,6 +707,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 693 | 707 | mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); |
| 694 | 708 | } |
| 695 | 709 | } |
| 710 | + | |
| 696 | 711 | /** |
| 697 | 712 | * 通知流上线 |
| 698 | 713 | */ |
| ... | ... | @@ -709,7 +724,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 709 | 724 | OnStreamChangedHookParam streamChangedHookParam = (OnStreamChangedHookParam)hookParam; |
| 710 | 725 | logger.info("[上级点播]拉流代理已经就绪, {}/{}", streamChangedHookParam.getApp(), streamChangedHookParam.getStream()); |
| 711 | 726 | dynamicTask.stop(callIdHeader.getCallId()); |
| 712 | - pushProxyStream(evt, request, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive, | |
| 727 | + pushProxyStream(evt, request, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive, | |
| 713 | 728 | mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); |
| 714 | 729 | }); |
| 715 | 730 | dynamicTask.startDelay(callIdHeader.getCallId(), () -> { |
| ... | ... | @@ -852,7 +867,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 852 | 867 | sendRtpItem.setCallId(callIdHeader.getCallId()); |
| 853 | 868 | |
| 854 | 869 | sendRtpItem.setFromTag(request.getFromTag()); |
| 855 | - SIPResponse response = sendStreamAck(responseSendItemMsg.getMediaServerItem(), request,sendRtpItem, platform, evt); | |
| 870 | + SIPResponse response = sendStreamAck(responseSendItemMsg.getMediaServerItem(), request, sendRtpItem, platform, evt); | |
| 856 | 871 | if (response != null) { |
| 857 | 872 | sendRtpItem.setToTag(response.getToTag()); |
| 858 | 873 | } |
| ... | ... | @@ -893,8 +908,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 893 | 908 | content.append("t=0 0\r\n"); |
| 894 | 909 | // 非严格模式端口不统一, 增加兼容性,修改为一个不为0的端口 |
| 895 | 910 | int localPort = sendRtpItem.getLocalPort(); |
| 896 | - if(localPort == 0) | |
| 897 | - { | |
| 911 | + if (localPort == 0) { | |
| 898 | 912 | localPort = new Random().nextInt(65535) + 1; |
| 899 | 913 | } |
| 900 | 914 | content.append("m=video " + localPort + " RTP/AVP 96\r\n"); |
| ... | ... | @@ -913,39 +927,75 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 913 | 927 | |
| 914 | 928 | try { |
| 915 | 929 | return responseSdpAck(request, content.toString(), platform); |
| 916 | - } catch (SipException e) { | |
| 917 | - logger.error("未处理的异常 ", e); | |
| 918 | - } catch (InvalidArgumentException e) { | |
| 919 | - logger.error("未处理的异常 ", e); | |
| 920 | - } catch (ParseException e) { | |
| 930 | + } catch (SipException | InvalidArgumentException | ParseException e) { | |
| 921 | 931 | logger.error("未处理的异常 ", e); |
| 922 | 932 | } |
| 923 | 933 | return null; |
| 924 | 934 | } |
| 925 | 935 | |
| 926 | - public void inviteFromDeviceHandle(SIPRequest request, String requesterId) { | |
| 936 | + public void inviteFromDeviceHandle(SIPRequest request, String requesterId, String channelId) { | |
| 937 | + | |
| 938 | + String realChannelId = null; | |
| 927 | 939 | |
| 928 | 940 | // 非上级平台请求,查询是否设备请求(通常为接收语音广播的设备) |
| 929 | 941 | Device device = redisCatchStorage.getDevice(requesterId); |
| 942 | + // 判断requesterId是设备还是通道 | |
| 943 | + if (device == null) { | |
| 944 | + device = storager.queryVideoDeviceByChannelId(requesterId); | |
| 945 | + realChannelId = requesterId; | |
| 946 | + }else { | |
| 947 | + realChannelId = channelId; | |
| 948 | + } | |
| 949 | + if (device == null) { | |
| 950 | + // 检查channelID是否可用 | |
| 951 | + device = redisCatchStorage.getDevice(channelId); | |
| 952 | + if (device == null) { | |
| 953 | + device = storager.queryVideoDeviceByChannelId(channelId); | |
| 954 | + realChannelId = channelId; | |
| 955 | + } | |
| 956 | + } | |
| 957 | + | |
| 958 | + if (device == null) { | |
| 959 | + logger.warn("来自设备的Invite请求,无法从请求信息中确定所属设备,已忽略,requesterId: {}/{}", requesterId, channelId); | |
| 960 | + try { | |
| 961 | + responseAck(request, Response.FORBIDDEN); | |
| 962 | + } catch (SipException | InvalidArgumentException | ParseException e) { | |
| 963 | + logger.error("[命令发送失败] 来自设备的Invite请求,无法从请求信息中确定所属设备 FORBIDDEN: {}", e.getMessage()); | |
| 964 | + } | |
| 965 | + return; | |
| 966 | + } | |
| 967 | + | |
| 968 | + AudioBroadcastCatch broadcastCatch = audioBroadcastManager.get(device.getDeviceId(), realChannelId); | |
| 969 | + if (broadcastCatch == null) { | |
| 970 | + logger.warn("来自设备的Invite请求非语音广播,已忽略,requesterId: {}/{}", requesterId, channelId); | |
| 971 | + try { | |
| 972 | + responseAck(request, Response.FORBIDDEN); | |
| 973 | + } catch (SipException | InvalidArgumentException | ParseException e) { | |
| 974 | + logger.error("[命令发送失败] 来自设备的Invite请求非语音广播 FORBIDDEN: {}", e.getMessage()); | |
| 975 | + } | |
| 976 | + return; | |
| 977 | + } | |
| 930 | 978 | if (device != null) { |
| 931 | 979 | logger.info("收到设备" + requesterId + "的语音广播Invite请求"); |
| 980 | + String key = VideoManagerConstants.BROADCAST_WAITE_INVITE + device.getDeviceId() + broadcastCatch.getChannelId(); | |
| 981 | + dynamicTask.stop(key); | |
| 932 | 982 | try { |
| 933 | 983 | responseAck(request, Response.TRYING); |
| 934 | 984 | } catch (SipException | InvalidArgumentException | ParseException e) { |
| 935 | 985 | logger.error("[命令发送失败] invite BAD_REQUEST: {}", e.getMessage()); |
| 986 | + playService.stopAudioBroadcast(device.getDeviceId(), broadcastCatch.getChannelId()); | |
| 987 | + return; | |
| 936 | 988 | } |
| 937 | 989 | String contentString = new String(request.getRawContent()); |
| 938 | - // jainSip不支持y=字段, 移除移除以解析。 | |
| 939 | - String ssrc = "0000000404"; | |
| 940 | 990 | |
| 941 | 991 | try { |
| 942 | 992 | Gb28181Sdp gb28181Sdp = SipUtils.parseSDP(contentString); |
| 943 | 993 | SessionDescription sdp = gb28181Sdp.getBaseSdb(); |
| 944 | 994 | // 获取支持的格式 |
| 945 | 995 | Vector mediaDescriptions = sdp.getMediaDescriptions(true); |
| 996 | + | |
| 946 | 997 | // 查看是否支持PS 负载96 |
| 947 | 998 | int port = -1; |
| 948 | - //boolean recvonly = false; | |
| 949 | 999 | boolean mediaTransmissionTCP = false; |
| 950 | 1000 | Boolean tcpActive = null; |
| 951 | 1001 | for (int i = 0; i < mediaDescriptions.size(); i++) { |
| ... | ... | @@ -977,26 +1027,147 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 977 | 1027 | try { |
| 978 | 1028 | responseAck(request, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415 |
| 979 | 1029 | } catch (SipException | InvalidArgumentException | ParseException e) { |
| 980 | - logger.error("[命令发送失败] invite 不支持的媒体格式,返回415, {}", e.getMessage()); | |
| 1030 | + logger.error("[命令发送失败] invite 不支持的媒体格式: {}", e.getMessage()); | |
| 1031 | + playService.stopAudioBroadcast(device.getDeviceId(), broadcastCatch.getChannelId()); | |
| 1032 | + return; | |
| 981 | 1033 | } |
| 982 | 1034 | return; |
| 983 | 1035 | } |
| 984 | - String username = sdp.getOrigin().getUsername(); | |
| 985 | - String addressStr = sdp.getConnection().getAddress(); | |
| 986 | - logger.info("设备{}请求语音流,地址:{}:{},ssrc:{}", username, addressStr, port, ssrc); | |
| 987 | - } catch (SdpException e) { | |
| 988 | - logger.error("[SDP解析异常]", e); | |
| 989 | - } | |
| 1036 | + String addressStr = sdp.getOrigin().getAddress(); | |
| 1037 | + logger.info("设备{}请求语音流,地址:{}:{},ssrc:{}, {}", requesterId, addressStr, port, gb28181Sdp.getSsrc(), | |
| 1038 | + mediaTransmissionTCP ? (tcpActive ? "TCP主动" : "TCP被动") : "UDP"); | |
| 1039 | + | |
| 1040 | + MediaServerItem mediaServerItem = broadcastCatch.getMediaServerItem(); | |
| 1041 | + if (mediaServerItem == null) { | |
| 1042 | + logger.warn("未找到语音喊话使用的zlm"); | |
| 1043 | + try { | |
| 1044 | + responseAck(request, Response.BUSY_HERE); | |
| 1045 | + } catch (SipException | InvalidArgumentException | ParseException e) { | |
| 1046 | + logger.error("[命令发送失败] invite 未找到可用的zlm: {}", e.getMessage()); | |
| 1047 | + playService.stopAudioBroadcast(device.getDeviceId(), broadcastCatch.getChannelId()); | |
| 1048 | + } | |
| 1049 | + return; | |
| 1050 | + } | |
| 1051 | + logger.info("设备{}请求语音流, 收流地址:{}:{},ssrc:{}, {}, 对讲方式:{}", requesterId, addressStr, port, gb28181Sdp.getSsrc(), | |
| 1052 | + mediaTransmissionTCP ? (tcpActive ? "TCP主动" : "TCP被动") : "UDP", sdp.getSessionName().getValue()); | |
| 1053 | + CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME); | |
| 990 | 1054 | |
| 1055 | + SendRtpItem sendRtpItem = zlmServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, gb28181Sdp.getSsrc(), requesterId, | |
| 1056 | + device.getDeviceId(), broadcastCatch.getChannelId(), | |
| 1057 | + mediaTransmissionTCP, false); | |
| 1058 | + | |
| 1059 | + if (sendRtpItem == null) { | |
| 1060 | + logger.warn("服务器端口资源不足"); | |
| 1061 | + try { | |
| 1062 | + responseAck(request, Response.BUSY_HERE); | |
| 1063 | + } catch (SipException | InvalidArgumentException | ParseException e) { | |
| 1064 | + logger.error("[命令发送失败] invite 服务器端口资源不足: {}", e.getMessage()); | |
| 1065 | + playService.stopAudioBroadcast(device.getDeviceId(), broadcastCatch.getChannelId()); | |
| 1066 | + return; | |
| 1067 | + } | |
| 1068 | + return; | |
| 1069 | + } | |
| 991 | 1070 | |
| 992 | 1071 | |
| 1072 | + sendRtpItem.setPlayType(InviteStreamType.BROADCAST); | |
| 1073 | + sendRtpItem.setCallId(callIdHeader.getCallId()); | |
| 1074 | + sendRtpItem.setPlatformId(requesterId); | |
| 1075 | + sendRtpItem.setStatus(1); | |
| 1076 | + sendRtpItem.setApp(broadcastCatch.getApp()); | |
| 1077 | + sendRtpItem.setStream(broadcastCatch.getStream()); | |
| 1078 | + sendRtpItem.setPt(8); | |
| 1079 | + sendRtpItem.setUsePs(false); | |
| 1080 | + sendRtpItem.setRtcp(false); | |
| 1081 | + sendRtpItem.setOnlyAudio(true); | |
| 1082 | + sendRtpItem.setTcp(mediaTransmissionTCP); | |
| 1083 | + if (tcpActive != null) { | |
| 1084 | + sendRtpItem.setTcpActive(tcpActive); | |
| 1085 | + } | |
| 1086 | + | |
| 1087 | + redisCatchStorage.updateSendRTPSever(sendRtpItem); | |
| 1088 | + | |
| 1089 | + Boolean streamReady = zlmServerFactory.isStreamReady(mediaServerItem, broadcastCatch.getApp(), broadcastCatch.getStream()); | |
| 1090 | + if (streamReady) { | |
| 1091 | + sendOk(device, sendRtpItem, sdp, request, mediaServerItem, mediaTransmissionTCP, gb28181Sdp.getSsrc()); | |
| 1092 | + } else { | |
| 1093 | + logger.warn("[语音通话], 未发现待推送的流,app={},stream={}", broadcastCatch.getApp(), broadcastCatch.getStream()); | |
| 1094 | + try { | |
| 1095 | + responseAck(request, Response.GONE); | |
| 1096 | + } catch (SipException | InvalidArgumentException | ParseException e) { | |
| 1097 | + logger.error("[命令发送失败] 语音通话 回复410失败, {}", e.getMessage()); | |
| 1098 | + return; | |
| 1099 | + } | |
| 1100 | + playService.stopAudioBroadcast(device.getDeviceId(), broadcastCatch.getChannelId()); | |
| 1101 | + } | |
| 1102 | + } catch (SdpException e) { | |
| 1103 | + logger.error("[SDP解析异常]", e); | |
| 1104 | + playService.stopAudioBroadcast(device.getDeviceId(), broadcastCatch.getChannelId()); | |
| 1105 | + } | |
| 993 | 1106 | } else { |
| 994 | 1107 | logger.warn("来自无效设备/平台的请求"); |
| 995 | 1108 | try { |
| 996 | - responseAck(request, Response.BAD_REQUEST);; // 不支持的格式,发415 | |
| 1109 | + responseAck(request, Response.BAD_REQUEST); | |
| 1110 | + ; // 不支持的格式,发415 | |
| 997 | 1111 | } catch (SipException | InvalidArgumentException | ParseException e) { |
| 998 | 1112 | logger.error("[命令发送失败] invite 来自无效设备/平台的请求, {}", e.getMessage()); |
| 999 | 1113 | } |
| 1000 | 1114 | } |
| 1001 | 1115 | } |
| 1116 | + | |
| 1117 | + SIPResponse sendOk(Device device, SendRtpItem sendRtpItem, SessionDescription sdp, SIPRequest request, MediaServerItem mediaServerItem, boolean mediaTransmissionTCP, String ssrc) { | |
| 1118 | + SIPResponse sipResponse = null; | |
| 1119 | + try { | |
| 1120 | + sendRtpItem.setStatus(2); | |
| 1121 | + redisCatchStorage.updateSendRTPSever(sendRtpItem); | |
| 1122 | + StringBuffer content = new StringBuffer(200); | |
| 1123 | + content.append("v=0\r\n"); | |
| 1124 | + content.append("o=" + config.getId() + " " + sdp.getOrigin().getSessionId() + " " + sdp.getOrigin().getSessionVersion() + " IN IP4 " + mediaServerItem.getSdpIp() + "\r\n"); | |
| 1125 | + content.append("s=Play\r\n"); | |
| 1126 | + content.append("c=IN IP4 " + mediaServerItem.getSdpIp() + "\r\n"); | |
| 1127 | + content.append("t=0 0\r\n"); | |
| 1128 | + | |
| 1129 | + if (mediaTransmissionTCP) { | |
| 1130 | + content.append("m=audio " + sendRtpItem.getLocalPort() + " TCP/RTP/AVP 8\r\n"); | |
| 1131 | + } else { | |
| 1132 | + content.append("m=audio " + sendRtpItem.getLocalPort() + " RTP/AVP 8\r\n"); | |
| 1133 | + } | |
| 1134 | + | |
| 1135 | + content.append("a=rtpmap:8 PCMA/8000/1\r\n"); | |
| 1136 | + | |
| 1137 | + content.append("a=sendonly\r\n"); | |
| 1138 | + if (sendRtpItem.isTcp()) { | |
| 1139 | + content.append("a=connection:new\r\n"); | |
| 1140 | + if (!sendRtpItem.isTcpActive()) { | |
| 1141 | + content.append("a=setup:active\r\n"); | |
| 1142 | + } else { | |
| 1143 | + content.append("a=setup:passive\r\n"); | |
| 1144 | + } | |
| 1145 | + } | |
| 1146 | + content.append("y=" + ssrc + "\r\n"); | |
| 1147 | + content.append("f=v/////a/1/8/1\r\n"); | |
| 1148 | + | |
| 1149 | + ParentPlatform parentPlatform = new ParentPlatform(); | |
| 1150 | + parentPlatform.setServerIP(device.getIp()); | |
| 1151 | + parentPlatform.setServerPort(device.getPort()); | |
| 1152 | + parentPlatform.setServerGBId(device.getDeviceId()); | |
| 1153 | + | |
| 1154 | + sipResponse = responseSdpAck(request, content.toString(), parentPlatform); | |
| 1155 | + | |
| 1156 | + AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(device.getDeviceId(), sendRtpItem.getChannelId()); | |
| 1157 | + | |
| 1158 | + audioBroadcastCatch.setStatus(AudioBroadcastCatchStatus.Ok); | |
| 1159 | + audioBroadcastCatch.setSipTransactionInfoByRequset(sipResponse); | |
| 1160 | + audioBroadcastManager.update(audioBroadcastCatch); | |
| 1161 | + streamSession.put(device.getDeviceId(), sendRtpItem.getChannelId(), request.getCallIdHeader().getCallId(), sendRtpItem.getStream(), sendRtpItem.getSsrc(), sendRtpItem.getMediaServerId(), sipResponse, InviteSessionType.BROADCAST); | |
| 1162 | + // 开启发流,大华在收到200OK后就会开始建立连接 | |
| 1163 | + if (!device.isBroadcastPushAfterAck()) { | |
| 1164 | + logger.info("[语音喊话] 回复200OK后发现 BroadcastPushAfterAck为False,现在开始推流"); | |
| 1165 | + playService.startPushStream(sendRtpItem, sipResponse, parentPlatform, request.getCallIdHeader()); | |
| 1166 | + } | |
| 1167 | + | |
| 1168 | + } catch (SipException | InvalidArgumentException | ParseException | SdpParseException e) { | |
| 1169 | + logger.error("[命令发送失败] 语音喊话 回复200OK(SDP): {}", e.getMessage()); | |
| 1170 | + } | |
| 1171 | + return sipResponse; | |
| 1172 | + } | |
| 1002 | 1173 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
| ... | ... | @@ -27,6 +27,9 @@ import org.springframework.beans.factory.annotation.Autowired; |
| 27 | 27 | import org.springframework.stereotype.Component; |
| 28 | 28 | import org.springframework.util.ObjectUtils; |
| 29 | 29 | |
| 30 | +import javax.sip.*; | |
| 31 | +import javax.sip.header.*; | |
| 32 | +import javax.sip.message.Request; | |
| 30 | 33 | import javax.sip.RequestEvent; |
| 31 | 34 | import javax.sip.SipException; |
| 32 | 35 | import javax.sip.header.AuthorizationHeader; | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java
| 1 | 1 | package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; |
| 2 | 2 | |
| 3 | +import com.genersoft.iot.vmp.common.VideoManagerConstants; | |
| 4 | +import com.genersoft.iot.vmp.conf.DynamicTask; | |
| 5 | +import com.genersoft.iot.vmp.conf.UserSetting; | |
| 3 | 6 | import com.genersoft.iot.vmp.gb28181.bean.CmdType; |
| 4 | 7 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| 5 | 8 | import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder; | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/info/InfoRequestProcessor.java
| ... | ... | @@ -109,7 +109,7 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I |
| 109 | 109 | String contentSubType = header.getContentSubType(); |
| 110 | 110 | if ("Application".equalsIgnoreCase(contentType) && "MANSRTSP".equalsIgnoreCase(contentSubType)) { |
| 111 | 111 | SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, null, callIdHeader.getCallId()); |
| 112 | - String streamId = sendRtpItem.getStreamId(); | |
| 112 | + String streamId = sendRtpItem.getStream(); | |
| 113 | 113 | InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId); |
| 114 | 114 | if (null == inviteInfo) { |
| 115 | 115 | responseAck(request, Response.NOT_FOUND, "stream " + streamId + " not found"); | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageHandlerAbstract.java
| ... | ... | @@ -5,10 +5,17 @@ import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| 5 | 5 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
| 6 | 6 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.cmd.CatalogQueryMessageHandler; |
| 7 | 7 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 8 | +import gov.nist.javax.sip.message.SIPRequest; | |
| 8 | 9 | import org.dom4j.Element; |
| 10 | +import org.slf4j.Logger; | |
| 11 | +import org.slf4j.LoggerFactory; | |
| 9 | 12 | import org.springframework.beans.factory.annotation.Autowired; |
| 10 | 13 | |
| 14 | +import javax.sip.InvalidArgumentException; | |
| 11 | 15 | import javax.sip.RequestEvent; |
| 16 | +import javax.sip.SipException; | |
| 17 | +import javax.sip.message.Response; | |
| 18 | +import java.text.ParseException; | |
| 12 | 19 | import java.util.Map; |
| 13 | 20 | import java.util.concurrent.ConcurrentHashMap; |
| 14 | 21 | |
| ... | ... | @@ -16,6 +23,8 @@ import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; |
| 16 | 23 | |
| 17 | 24 | public abstract class MessageHandlerAbstract extends SIPRequestProcessorParent implements IMessageHandler{ |
| 18 | 25 | |
| 26 | + private Logger logger = LoggerFactory.getLogger(MessageHandlerAbstract.class); | |
| 27 | + | |
| 19 | 28 | public Map<String, IMessageHandler> messageHandlerMap = new ConcurrentHashMap<>(); |
| 20 | 29 | |
| 21 | 30 | @Autowired |
| ... | ... | @@ -28,6 +37,14 @@ public abstract class MessageHandlerAbstract extends SIPRequestProcessorParent i |
| 28 | 37 | @Override |
| 29 | 38 | public void handForDevice(RequestEvent evt, Device device, Element element) { |
| 30 | 39 | String cmd = getText(element, "CmdType"); |
| 40 | + if (cmd == null) { | |
| 41 | + try { | |
| 42 | + responseAck((SIPRequest) evt.getRequest(), Response.OK); | |
| 43 | + } catch (SipException | InvalidArgumentException | ParseException e) { | |
| 44 | + logger.error("[命令发送失败] 回复200 OK: {}", e.getMessage()); | |
| 45 | + } | |
| 46 | + return; | |
| 47 | + } | |
| 31 | 48 | IMessageHandler messageHandler = messageHandlerMap.get(cmd); |
| 32 | 49 | |
| 33 | 50 | if (messageHandler != null) { | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/BroadcastNotifyMessageHandler.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd; | |
| 2 | + | |
| 3 | +import com.alibaba.fastjson2.JSONObject; | |
| 4 | +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; | |
| 5 | +import com.genersoft.iot.vmp.gb28181.bean.*; | |
| 6 | +import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; | |
| 7 | +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; | |
| 8 | +import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; | |
| 9 | +import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; | |
| 10 | +import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler; | |
| 11 | +import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; | |
| 12 | +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | |
| 13 | +import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; | |
| 14 | +import com.genersoft.iot.vmp.service.IDeviceService; | |
| 15 | +import com.genersoft.iot.vmp.service.IMediaServerService; | |
| 16 | +import com.genersoft.iot.vmp.service.IPlatformService; | |
| 17 | +import com.genersoft.iot.vmp.service.IPlayService; | |
| 18 | +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | |
| 19 | +import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | |
| 20 | +import gov.nist.javax.sip.message.SIPRequest; | |
| 21 | +import org.dom4j.Element; | |
| 22 | +import org.slf4j.Logger; | |
| 23 | +import org.slf4j.LoggerFactory; | |
| 24 | +import org.springframework.beans.factory.InitializingBean; | |
| 25 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 26 | +import org.springframework.stereotype.Component; | |
| 27 | + | |
| 28 | +import javax.sip.InvalidArgumentException; | |
| 29 | +import javax.sip.RequestEvent; | |
| 30 | +import javax.sip.SipException; | |
| 31 | +import javax.sip.message.Response; | |
| 32 | +import java.text.ParseException; | |
| 33 | + | |
| 34 | +/** | |
| 35 | + * 状态信息(心跳)报送 | |
| 36 | + */ | |
| 37 | +@Component | |
| 38 | +public class BroadcastNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { | |
| 39 | + | |
| 40 | + private Logger logger = LoggerFactory.getLogger(BroadcastNotifyMessageHandler.class); | |
| 41 | + private final static String cmdType = "Broadcast"; | |
| 42 | + | |
| 43 | + @Autowired | |
| 44 | + private NotifyMessageHandler notifyMessageHandler; | |
| 45 | + | |
| 46 | + @Autowired | |
| 47 | + private IVideoManagerStorage storage; | |
| 48 | + | |
| 49 | + @Autowired | |
| 50 | + private ISIPCommanderForPlatform commanderForPlatform; | |
| 51 | + | |
| 52 | + @Autowired | |
| 53 | + private IMediaServerService mediaServerService; | |
| 54 | + | |
| 55 | + @Autowired | |
| 56 | + private IPlayService playService; | |
| 57 | + | |
| 58 | + @Autowired | |
| 59 | + private IDeviceService deviceService; | |
| 60 | + | |
| 61 | + @Autowired | |
| 62 | + private IPlatformService platformService; | |
| 63 | + | |
| 64 | + @Autowired | |
| 65 | + private AudioBroadcastManager audioBroadcastManager; | |
| 66 | + | |
| 67 | + @Autowired | |
| 68 | + private ZLMServerFactory zlmServerFactory; | |
| 69 | + | |
| 70 | + @Autowired | |
| 71 | + private IRedisCatchStorage redisCatchStorage; | |
| 72 | + | |
| 73 | + @Override | |
| 74 | + public void afterPropertiesSet() throws Exception { | |
| 75 | + notifyMessageHandler.addHandler(cmdType, this); | |
| 76 | + } | |
| 77 | + | |
| 78 | + @Override | |
| 79 | + public void handForDevice(RequestEvent evt, Device device, Element element) { | |
| 80 | + | |
| 81 | + } | |
| 82 | + | |
| 83 | + @Override | |
| 84 | + public void handForPlatform(RequestEvent evt, ParentPlatform platform, Element rootElement) { | |
| 85 | + // 来自上级平台的语音喊话请求 | |
| 86 | + SIPRequest request = (SIPRequest) evt.getRequest(); | |
| 87 | + try { | |
| 88 | + Element snElement = rootElement.element("SN"); | |
| 89 | + if (snElement == null) { | |
| 90 | + responseAck(request, Response.BAD_REQUEST, "sn must not null"); | |
| 91 | + return; | |
| 92 | + } | |
| 93 | + String sn = snElement.getText(); | |
| 94 | + Element targetIDElement = rootElement.element("TargetID"); | |
| 95 | + if (targetIDElement == null) { | |
| 96 | + responseAck(request, Response.BAD_REQUEST, "TargetID must not null"); | |
| 97 | + return; | |
| 98 | + } | |
| 99 | + String targetId = targetIDElement.getText(); | |
| 100 | + | |
| 101 | + | |
| 102 | + logger.info("[国标级联 语音喊话] platform: {}, channel: {}", platform.getServerGBId(), targetId); | |
| 103 | + | |
| 104 | + DeviceChannel deviceChannel = storage.queryChannelInParentPlatform(platform.getServerGBId(), targetId); | |
| 105 | + if (deviceChannel == null) { | |
| 106 | + logger.warn("[国标级联 语音喊话] 未找到通道 platform: {}, channel: {}", platform.getServerGBId(), targetId); | |
| 107 | + responseAck(request, Response.NOT_FOUND, "TargetID not found"); | |
| 108 | + return; | |
| 109 | + } | |
| 110 | + // 向下级发送语音的喊话请求 | |
| 111 | + Device device = deviceService.getDevice(deviceChannel.getDeviceId()); | |
| 112 | + if (device == null) { | |
| 113 | + responseAck(request, Response.NOT_FOUND, "device not found"); | |
| 114 | + return; | |
| 115 | + } | |
| 116 | + responseAck(request, Response.OK); | |
| 117 | + | |
| 118 | + // 查看语音通道是否已经建立并且已经在使用 | |
| 119 | + if (playService.audioBroadcastInUse(device, targetId)) { | |
| 120 | + commanderForPlatform.broadcastResultCmd(platform, deviceChannel, sn, false,null, null); | |
| 121 | + return; | |
| 122 | + } | |
| 123 | + | |
| 124 | + MediaServerItem mediaServerForMinimumLoad = mediaServerService.getMediaServerForMinimumLoad(null); | |
| 125 | + commanderForPlatform.broadcastResultCmd(platform, deviceChannel, sn, true, eventResult->{ | |
| 126 | + logger.info("[国标级联] 语音喊话 回复失败 platform: {}, 错误:{}/{}", platform.getServerGBId(), eventResult.statusCode, eventResult.msg); | |
| 127 | + }, eventResult->{ | |
| 128 | + | |
| 129 | + // 消息发送成功, 向上级发送invite,获取推流 | |
| 130 | + try { | |
| 131 | + platformService.broadcastInvite(platform, deviceChannel.getChannelId(), mediaServerForMinimumLoad, (mediaServerItem, hookParam)->{ | |
| 132 | + OnStreamChangedHookParam streamChangedHookParam = (OnStreamChangedHookParam)hookParam; | |
| 133 | + // 上级平台推流成功 | |
| 134 | + AudioBroadcastCatch broadcastCatch = audioBroadcastManager.get(device.getDeviceId(), targetId); | |
| 135 | + if (broadcastCatch != null ) { | |
| 136 | + if (playService.audioBroadcastInUse(device, targetId)) { | |
| 137 | + logger.info("[国标级联] 语音喊话 设备正在使用中 platform: {}, channel: {}", | |
| 138 | + platform.getServerGBId(), deviceChannel.getChannelId()); | |
| 139 | + // 查看语音通道已经建立且已经占用 回复BYE | |
| 140 | + platformService.stopBroadcast(platform, deviceChannel, streamChangedHookParam.getStream(), true, mediaServerItem); | |
| 141 | + }else { | |
| 142 | + // 查看语音通道已经建立但是未占用 | |
| 143 | + broadcastCatch.setApp(streamChangedHookParam.getApp()); | |
| 144 | + broadcastCatch.setStream(streamChangedHookParam.getStream()); | |
| 145 | + broadcastCatch.setMediaServerItem(mediaServerItem); | |
| 146 | + audioBroadcastManager.update(broadcastCatch); | |
| 147 | + // 推流到设备 | |
| 148 | + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, targetId, streamChangedHookParam.getStream(), null); | |
| 149 | + if (sendRtpItem == null) { | |
| 150 | + logger.warn("[国标级联] 语音喊话 异常,未找到发流信息, channelId: {}, stream: {}", targetId, streamChangedHookParam.getStream()); | |
| 151 | + logger.info("[国标级联] 语音喊话 重新开始,channelId: {}, stream: {}", targetId, streamChangedHookParam.getStream()); | |
| 152 | + try { | |
| 153 | + playService.audioBroadcastCmd(device, targetId, mediaServerItem, streamChangedHookParam.getApp(), streamChangedHookParam.getStream(), 60, true, msg -> { | |
| 154 | + logger.info("[语音喊话] 通道建立成功, device: {}, channel: {}", device.getDeviceId(), targetId); | |
| 155 | + }); | |
| 156 | + } catch (SipException | InvalidArgumentException | ParseException e) { | |
| 157 | + logger.info("[消息发送失败] 国标级联 语音喊话 platform: {}", platform.getServerGBId()); | |
| 158 | + } | |
| 159 | + }else { | |
| 160 | + // 发流 | |
| 161 | + JSONObject jsonObject = zlmServerFactory.startSendRtp(mediaServerItem, sendRtpItem); | |
| 162 | + if (jsonObject != null && jsonObject.getInteger("code") == 0 ) { | |
| 163 | + logger.info("[语音喊话] 自动推流成功, device: {}, channel: {}", device.getDeviceId(), targetId); | |
| 164 | + }else { | |
| 165 | + logger.info("[语音喊话] 推流失败, 结果: {}", jsonObject); | |
| 166 | + } | |
| 167 | + } | |
| 168 | + } | |
| 169 | + }else { | |
| 170 | + try { | |
| 171 | + playService.audioBroadcastCmd(device, targetId, mediaServerItem, streamChangedHookParam.getApp(), streamChangedHookParam.getStream(), 60, true, msg -> { | |
| 172 | + logger.info("[语音喊话] 通道建立成功, device: {}, channel: {}", device.getDeviceId(), targetId); | |
| 173 | + }); | |
| 174 | + } catch (SipException | InvalidArgumentException | ParseException e) { | |
| 175 | + logger.info("[消息发送失败] 国标级联 语音喊话 platform: {}", platform.getServerGBId()); | |
| 176 | + } | |
| 177 | + } | |
| 178 | + | |
| 179 | + }, eventResultForBroadcastInvite -> { | |
| 180 | + // 收到错误 | |
| 181 | + logger.info("[国标级联-语音喊话] 与下级通道建立失败 device: {}, channel: {}, 错误:{}/{}", device.getDeviceId(), | |
| 182 | + targetId, eventResultForBroadcastInvite.statusCode, eventResultForBroadcastInvite.msg); | |
| 183 | + }, (code, msg)->{ | |
| 184 | + // 超时 | |
| 185 | + logger.info("[国标级联-语音喊话] 与下级通道建立超时 device: {}, channel: {}, 错误:{}/{}", device.getDeviceId(), | |
| 186 | + targetId, code, msg); | |
| 187 | + }); | |
| 188 | + } catch (SipException | InvalidArgumentException | ParseException e) { | |
| 189 | + logger.info("[消息发送失败] 国标级联 语音喊话 invite消息 platform: {}", platform.getServerGBId()); | |
| 190 | + } | |
| 191 | + }); | |
| 192 | + } catch (SipException | InvalidArgumentException | ParseException e) { | |
| 193 | + logger.info("[消息发送失败] 国标级联 语音喊话 platform: {}", platform.getServerGBId()); | |
| 194 | + } | |
| 195 | + | |
| 196 | + } | |
| 197 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java
| ... | ... | @@ -102,7 +102,7 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i |
| 102 | 102 | |
| 103 | 103 | try { |
| 104 | 104 | cmder.streamByeCmd(device, ssrcTransaction.getChannelId(), null, callIdHeader.getCallId()); |
| 105 | - } catch (InvalidArgumentException | ParseException | SsrcTransactionNotFoundException | SipException e) { | |
| 105 | + } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) { | |
| 106 | 106 | logger.error("[录像流]推送完毕,收到关流通知, 发送BYE失败 {}", e.getMessage()); |
| 107 | 107 | } |
| 108 | 108 | // 去除监听流注销自动停止下载的监听 | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/BroadcastResponseMessageHandler.java
| 1 | 1 | package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd; |
| 2 | 2 | |
| 3 | -import com.alibaba.fastjson2.JSONObject; | |
| 3 | +import com.genersoft.iot.vmp.common.VideoManagerConstants; | |
| 4 | +import com.genersoft.iot.vmp.conf.DynamicTask; | |
| 5 | +import com.genersoft.iot.vmp.gb28181.bean.AudioBroadcastCatch; | |
| 6 | +import com.genersoft.iot.vmp.gb28181.bean.AudioBroadcastCatchStatus; | |
| 4 | 7 | import com.genersoft.iot.vmp.gb28181.bean.Device; |
| 5 | 8 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| 9 | +import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; | |
| 6 | 10 | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
| 7 | -import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; | |
| 8 | 11 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
| 9 | 12 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; |
| 10 | 13 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; |
| 11 | -import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; | |
| 14 | +import com.genersoft.iot.vmp.service.IPlayService; | |
| 12 | 15 | import gov.nist.javax.sip.message.SIPRequest; |
| 13 | 16 | import org.dom4j.Element; |
| 14 | 17 | import org.slf4j.Logger; |
| ... | ... | @@ -35,7 +38,13 @@ public class BroadcastResponseMessageHandler extends SIPRequestProcessorParent i |
| 35 | 38 | private ResponseMessageHandler responseMessageHandler; |
| 36 | 39 | |
| 37 | 40 | @Autowired |
| 38 | - private DeferredResultHolder deferredResultHolder; | |
| 41 | + private DynamicTask dynamicTask; | |
| 42 | + | |
| 43 | + @Autowired | |
| 44 | + private AudioBroadcastManager audioBroadcastManager; | |
| 45 | + | |
| 46 | + @Autowired | |
| 47 | + private IPlayService playService; | |
| 39 | 48 | |
| 40 | 49 | @Override |
| 41 | 50 | public void afterPropertiesSet() throws Exception { |
| ... | ... | @@ -44,23 +53,38 @@ public class BroadcastResponseMessageHandler extends SIPRequestProcessorParent i |
| 44 | 53 | |
| 45 | 54 | @Override |
| 46 | 55 | public void handForDevice(RequestEvent evt, Device device, Element rootElement) { |
| 56 | + | |
| 57 | + SIPRequest request = (SIPRequest) evt.getRequest(); | |
| 47 | 58 | try { |
| 48 | 59 | String channelId = getText(rootElement, "DeviceID"); |
| 49 | - String key = DeferredResultHolder.CALLBACK_CMD_BROADCAST + device.getDeviceId() + channelId; | |
| 50 | - // 回复200 OK | |
| 51 | - responseAck((SIPRequest) evt.getRequest(), Response.OK); | |
| 52 | - // 此处是对本平台发出Broadcast指令的应答 | |
| 53 | - JSONObject json = new JSONObject(); | |
| 54 | - XmlUtil.node2Json(rootElement, json); | |
| 55 | - if (logger.isDebugEnabled()) { | |
| 56 | - logger.debug(json.toJSONString()); | |
| 60 | + if (!audioBroadcastManager.exit(device.getDeviceId(), channelId)) { | |
| 61 | + // 回复410 | |
| 62 | + responseAck((SIPRequest) evt.getRequest(), Response.GONE); | |
| 63 | + return; | |
| 57 | 64 | } |
| 58 | - RequestMessage msg = new RequestMessage(); | |
| 59 | - msg.setKey(key); | |
| 60 | - msg.setData(json); | |
| 61 | - deferredResultHolder.invokeAllResult(msg); | |
| 62 | - | |
| 65 | + String result = getText(rootElement, "Result"); | |
| 66 | + Element infoElement = rootElement.element("Info"); | |
| 67 | + String reason = null; | |
| 68 | + if (infoElement != null) { | |
| 69 | + reason = getText(infoElement, "Reason"); | |
| 70 | + } | |
| 71 | + logger.info("[语音广播]回复:{}, {}/{}", reason == null? result : result + ": " + reason, device.getDeviceId(), channelId ); | |
| 63 | 72 | |
| 73 | + // 回复200 OK | |
| 74 | + responseAck(request, Response.OK); | |
| 75 | + if (result.equalsIgnoreCase("OK")) { | |
| 76 | + AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(device.getDeviceId(), channelId); | |
| 77 | + audioBroadcastCatch.setStatus(AudioBroadcastCatchStatus.WaiteInvite); | |
| 78 | + audioBroadcastManager.update(audioBroadcastCatch); | |
| 79 | + // 等待invite消息, 超时则结束 | |
| 80 | + String key = VideoManagerConstants.BROADCAST_WAITE_INVITE + device.getDeviceId() + channelId; | |
| 81 | + dynamicTask.startDelay(key, ()->{ | |
| 82 | + logger.info("[语音广播]等待invite消息超时:{}/{}", device.getDeviceId(), channelId); | |
| 83 | + playService.stopAudioBroadcast(device.getDeviceId(), channelId); | |
| 84 | + }, 2000); | |
| 85 | + }else { | |
| 86 | + playService.stopAudioBroadcast(device.getDeviceId(), channelId); | |
| 87 | + } | |
| 64 | 88 | } catch (ParseException | SipException | InvalidArgumentException e) { |
| 65 | 89 | logger.error("[命令发送失败] 国标级联 语音喊话: {}", e.getMessage()); |
| 66 | 90 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java
| ... | ... | @@ -39,6 +39,7 @@ import java.util.concurrent.atomic.AtomicBoolean; |
| 39 | 39 | public class CatalogResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { |
| 40 | 40 | |
| 41 | 41 | private Logger logger = LoggerFactory.getLogger(CatalogResponseMessageHandler.class); |
| 42 | + | |
| 42 | 43 | private final String cmdType = "Catalog"; |
| 43 | 44 | |
| 44 | 45 | @Autowired | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java
| ... | ... | @@ -19,6 +19,9 @@ import javax.sdp.SessionDescription; |
| 19 | 19 | import javax.sip.InvalidArgumentException; |
| 20 | 20 | import javax.sip.ResponseEvent; |
| 21 | 21 | import javax.sip.SipException; |
| 22 | +import javax.sip.InvalidArgumentException; | |
| 23 | +import javax.sip.ResponseEvent; | |
| 24 | +import javax.sip.SipException; | |
| 22 | 25 | import javax.sip.SipFactory; |
| 23 | 26 | import javax.sip.address.SipURI; |
| 24 | 27 | import javax.sip.message.Request; | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java
| ... | ... | @@ -140,6 +140,26 @@ public class SipUtils { |
| 140 | 140 | return builder.toString(); |
| 141 | 141 | } |
| 142 | 142 | |
| 143 | + public static String getNewCallId() { | |
| 144 | + return (int) Math.floor(Math.random() * 1000000000) + ""; | |
| 145 | + } | |
| 146 | + | |
| 147 | + public static int getTypeCodeFromGbCode(String deviceId) { | |
| 148 | + if (ObjectUtils.isEmpty(deviceId)) { | |
| 149 | + return 0; | |
| 150 | + } | |
| 151 | + return Integer.parseInt(deviceId.substring(10, 13)); | |
| 152 | + } | |
| 153 | + | |
| 154 | + /** | |
| 155 | + * 判断是否是前端外围设备 | |
| 156 | + * @param deviceId | |
| 157 | + * @return | |
| 158 | + */ | |
| 159 | + public static boolean isFrontEnd(String deviceId) { | |
| 160 | + int typeCodeFromGbCode = getTypeCodeFromGbCode(deviceId); | |
| 161 | + return typeCodeFromGbCode > 130 && typeCodeFromGbCode < 199; | |
| 162 | + } | |
| 143 | 163 | /** |
| 144 | 164 | * 从请求中获取设备ip地址和端口号 |
| 145 | 165 | * @param request 请求 | ... | ... |
src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java
| ... | ... | @@ -38,7 +38,7 @@ public class AssistRESTfulUtils { |
| 38 | 38 | private OkHttpClient getClient(){ |
| 39 | 39 | return getClient(null); |
| 40 | 40 | } |
| 41 | - | |
| 41 | + | |
| 42 | 42 | private OkHttpClient getClient(Integer readTimeOut){ |
| 43 | 43 | if (client == null) { |
| 44 | 44 | if (readTimeOut == null) { |
| ... | ... | @@ -251,7 +251,7 @@ public class AssistRESTfulUtils { |
| 251 | 251 | |
| 252 | 252 | public JSONObject addTask(MediaServerItem mediaServerItem, String app, String stream, String startTime, |
| 253 | 253 | String endTime, String callId, List<String> filePathList, String remoteHost) { |
| 254 | - | |
| 254 | + | |
| 255 | 255 | JSONObject videoTaskInfoJSON = new JSONObject(); |
| 256 | 256 | videoTaskInfoJSON.put("app", app); |
| 257 | 257 | videoTaskInfoJSON.put("stream", stream); | ... | ... |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
| 1 | -package com.genersoft.iot.vmp.media.zlm; | |
| 2 | - | |
| 3 | -import com.alibaba.fastjson2.JSON; | |
| 4 | -import com.alibaba.fastjson2.JSONObject; | |
| 5 | -import com.genersoft.iot.vmp.common.InviteInfo; | |
| 6 | -import com.genersoft.iot.vmp.common.InviteSessionType; | |
| 7 | -import com.genersoft.iot.vmp.common.StreamInfo; | |
| 8 | -import com.genersoft.iot.vmp.common.VideoManagerConstants; | |
| 9 | -import com.genersoft.iot.vmp.conf.UserSetting; | |
| 10 | -import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; | |
| 11 | -import com.genersoft.iot.vmp.gb28181.bean.*; | |
| 12 | -import com.genersoft.iot.vmp.gb28181.event.EventPublisher; | |
| 13 | -import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; | |
| 14 | -import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; | |
| 15 | -import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | |
| 16 | -import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; | |
| 17 | -import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; | |
| 18 | -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | |
| 19 | -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; | |
| 20 | -import com.genersoft.iot.vmp.media.zlm.dto.HookType; | |
| 21 | -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | |
| 22 | -import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; | |
| 23 | -import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; | |
| 24 | -import com.genersoft.iot.vmp.media.zlm.dto.hook.*; | |
| 25 | -import com.genersoft.iot.vmp.service.*; | |
| 26 | -import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; | |
| 27 | -import com.genersoft.iot.vmp.service.bean.SSRCInfo; | |
| 28 | -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | |
| 29 | -import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | |
| 30 | -import com.genersoft.iot.vmp.utils.DateUtil; | |
| 31 | -import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; | |
| 32 | -import com.genersoft.iot.vmp.vmanager.bean.OtherPsSendInfo; | |
| 33 | -import com.genersoft.iot.vmp.vmanager.bean.OtherRtpSendInfo; | |
| 34 | -import com.genersoft.iot.vmp.vmanager.bean.StreamContent; | |
| 35 | -import org.slf4j.Logger; | |
| 36 | -import org.slf4j.LoggerFactory; | |
| 37 | -import org.springframework.beans.factory.annotation.Autowired; | |
| 38 | -import org.springframework.beans.factory.annotation.Qualifier; | |
| 39 | -import org.springframework.data.redis.core.RedisTemplate; | |
| 40 | -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; | |
| 41 | -import org.springframework.util.ObjectUtils; | |
| 42 | -import org.springframework.web.bind.annotation.*; | |
| 43 | -import org.springframework.web.context.request.async.DeferredResult; | |
| 44 | - | |
| 45 | -import javax.servlet.http.HttpServletRequest; | |
| 46 | -import javax.sip.InvalidArgumentException; | |
| 47 | -import javax.sip.SipException; | |
| 48 | -import java.text.ParseException; | |
| 49 | -import java.util.HashMap; | |
| 50 | -import java.util.List; | |
| 51 | -import java.util.Map; | |
| 52 | -import java.util.UUID; | |
| 53 | - | |
| 54 | -/** | |
| 55 | - * @description:针对 ZLMediaServer的hook事件监听 | |
| 56 | - * @author: swwheihei | |
| 57 | - * @date: 2020年5月8日 上午10:46:48 | |
| 58 | - */ | |
| 59 | -@RestController | |
| 60 | -@RequestMapping("/index/hook") | |
| 61 | -public class ZLMHttpHookListener { | |
| 62 | - | |
| 63 | - private final static Logger logger = LoggerFactory.getLogger(ZLMHttpHookListener.class); | |
| 64 | - | |
| 65 | - @Autowired | |
| 66 | - private SIPCommander cmder; | |
| 67 | - | |
| 68 | - @Autowired | |
| 69 | - private SIPCommanderFroPlatform commanderFroPlatform; | |
| 70 | - | |
| 71 | - @Autowired | |
| 72 | - private IPlayService playService; | |
| 73 | - | |
| 74 | - @Autowired | |
| 75 | - private IVideoManagerStorage storager; | |
| 76 | - | |
| 77 | - @Autowired | |
| 78 | - private IRedisCatchStorage redisCatchStorage; | |
| 79 | - | |
| 80 | - @Autowired | |
| 81 | - private IInviteStreamService inviteStreamService; | |
| 82 | - | |
| 83 | - @Autowired | |
| 84 | - private IDeviceService deviceService; | |
| 85 | - | |
| 86 | - @Autowired | |
| 87 | - private IMediaServerService mediaServerService; | |
| 88 | - | |
| 89 | - @Autowired | |
| 90 | - private IStreamProxyService streamProxyService; | |
| 91 | - | |
| 92 | - @Autowired | |
| 93 | - private DeferredResultHolder resultHolder; | |
| 94 | - | |
| 95 | - @Autowired | |
| 96 | - private IMediaService mediaService; | |
| 97 | - | |
| 98 | - @Autowired | |
| 99 | - private EventPublisher eventPublisher; | |
| 100 | - | |
| 101 | - @Autowired | |
| 102 | - private ZLMMediaListManager zlmMediaListManager; | |
| 103 | - | |
| 104 | - @Autowired | |
| 105 | - private ZlmHttpHookSubscribe subscribe; | |
| 106 | - | |
| 107 | - @Autowired | |
| 108 | - private UserSetting userSetting; | |
| 109 | - | |
| 110 | - @Autowired | |
| 111 | - private IUserService userService; | |
| 112 | - | |
| 113 | - @Autowired | |
| 114 | - private ICloudRecordService cloudRecordService; | |
| 115 | - | |
| 116 | - @Autowired | |
| 117 | - private VideoStreamSessionManager sessionManager; | |
| 118 | - | |
| 119 | - @Autowired | |
| 120 | - private AssistRESTfulUtils assistRESTfulUtils; | |
| 121 | - | |
| 122 | - @Autowired | |
| 123 | - private SSRCFactory ssrcFactory; | |
| 124 | - | |
| 125 | - @Qualifier("taskExecutor") | |
| 126 | - @Autowired | |
| 127 | - private ThreadPoolTaskExecutor taskExecutor; | |
| 128 | - | |
| 129 | - @Autowired | |
| 130 | - private RedisTemplate<Object, Object> redisTemplate; | |
| 131 | - | |
| 132 | - /** | |
| 133 | - * 服务器定时上报时间,上报间隔可配置,默认10s上报一次 | |
| 134 | - */ | |
| 135 | - @ResponseBody | |
| 136 | - | |
| 137 | - @PostMapping(value = "/on_server_keepalive", produces = "application/json;charset=UTF-8") | |
| 138 | - public HookResult onServerKeepalive(@RequestBody OnServerKeepaliveHookParam param) { | |
| 139 | - | |
| 140 | - | |
| 141 | - taskExecutor.execute(() -> { | |
| 142 | - List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_keepalive); | |
| 143 | - if (subscribes != null && subscribes.size() > 0) { | |
| 144 | - for (ZlmHttpHookSubscribe.Event subscribe : subscribes) { | |
| 145 | - subscribe.response(null, param); | |
| 146 | - } | |
| 147 | - } | |
| 148 | - }); | |
| 149 | - mediaServerService.updateMediaServerKeepalive(param.getMediaServerId(), param.getData()); | |
| 150 | - | |
| 151 | - return HookResult.SUCCESS(); | |
| 152 | - } | |
| 153 | - | |
| 154 | - /** | |
| 155 | - * 播放器鉴权事件,rtsp/rtmp/http-flv/ws-flv/hls的播放都将触发此鉴权事件。 | |
| 156 | - */ | |
| 157 | - @ResponseBody | |
| 158 | - | |
| 159 | - @PostMapping(value = "/on_play", produces = "application/json;charset=UTF-8") | |
| 160 | - public HookResult onPlay(@RequestBody OnPlayHookParam param) { | |
| 161 | - if (logger.isDebugEnabled()) { | |
| 162 | - logger.debug("[ZLM HOOK] 播放鉴权:{}->{}" + param.getMediaServerId(), param); | |
| 163 | - } | |
| 164 | - String mediaServerId = param.getMediaServerId(); | |
| 165 | - | |
| 166 | - taskExecutor.execute(() -> { | |
| 167 | - JSONObject json = (JSONObject) JSON.toJSON(param); | |
| 168 | - ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_play, json); | |
| 169 | - if (subscribe != null) { | |
| 170 | - MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); | |
| 171 | - if (mediaInfo != null) { | |
| 172 | - subscribe.response(mediaInfo, param); | |
| 173 | - } | |
| 174 | - } | |
| 175 | - }); | |
| 176 | - if (!"rtp".equals(param.getApp())) { | |
| 177 | - Map<String, String> paramMap = urlParamToMap(param.getParams()); | |
| 178 | - StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream()); | |
| 179 | - if (streamAuthorityInfo != null && streamAuthorityInfo.getCallId() != null && !streamAuthorityInfo.getCallId().equals(paramMap.get("callId"))) { | |
| 180 | - return new HookResult(401, "Unauthorized"); | |
| 181 | - } | |
| 182 | - } | |
| 183 | - | |
| 184 | - return HookResult.SUCCESS(); | |
| 185 | - } | |
| 186 | - | |
| 187 | - /** | |
| 188 | - * rtsp/rtmp/rtp推流鉴权事件。 | |
| 189 | - */ | |
| 190 | - @ResponseBody | |
| 191 | - @PostMapping(value = "/on_publish", produces = "application/json;charset=UTF-8") | |
| 192 | - public HookResultForOnPublish onPublish(@RequestBody OnPublishHookParam param) { | |
| 193 | - | |
| 194 | - JSONObject json = (JSONObject) JSON.toJSON(param); | |
| 195 | - | |
| 196 | - logger.info("[ZLM HOOK]推流鉴权:{}->{}", param.getMediaServerId(), param); | |
| 197 | - | |
| 198 | - String mediaServerId = json.getString("mediaServerId"); | |
| 199 | - MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); | |
| 200 | - if (mediaInfo == null) { | |
| 201 | - return new HookResultForOnPublish(200, "success"); | |
| 202 | - } | |
| 203 | - // 推流鉴权的处理 | |
| 204 | - if (!"rtp".equals(param.getApp())) { | |
| 205 | - StreamProxyItem stream = streamProxyService.getStreamProxyByAppAndStream(param.getApp(), param.getStream()); | |
| 206 | - if (stream != null) { | |
| 207 | - HookResultForOnPublish result = HookResultForOnPublish.SUCCESS(); | |
| 208 | - result.setEnable_audio(stream.isEnableAudio()); | |
| 209 | - result.setEnable_mp4(stream.isEnableMp4()); | |
| 210 | - return result; | |
| 211 | - } | |
| 212 | - if (userSetting.getPushAuthority()) { | |
| 213 | - // 推流鉴权 | |
| 214 | - if (param.getParams() == null) { | |
| 215 | - logger.info("推流鉴权失败: 缺少必要参数:sign=md5(user表的pushKey)"); | |
| 216 | - return new HookResultForOnPublish(401, "Unauthorized"); | |
| 217 | - } | |
| 218 | - Map<String, String> paramMap = urlParamToMap(param.getParams()); | |
| 219 | - String sign = paramMap.get("sign"); | |
| 220 | - if (sign == null) { | |
| 221 | - logger.info("推流鉴权失败: 缺少必要参数:sign=md5(user表的pushKey)"); | |
| 222 | - return new HookResultForOnPublish(401, "Unauthorized"); | |
| 223 | - } | |
| 224 | - // 推流自定义播放鉴权码 | |
| 225 | - String callId = paramMap.get("callId"); | |
| 226 | - // 鉴权配置 | |
| 227 | - boolean hasAuthority = userService.checkPushAuthority(callId, sign); | |
| 228 | - if (!hasAuthority) { | |
| 229 | - logger.info("推流鉴权失败: sign 无权限: callId={}. sign={}", callId, sign); | |
| 230 | - return new HookResultForOnPublish(401, "Unauthorized"); | |
| 231 | - } | |
| 232 | - StreamAuthorityInfo streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(param); | |
| 233 | - streamAuthorityInfo.setCallId(callId); | |
| 234 | - streamAuthorityInfo.setSign(sign); | |
| 235 | - // 鉴权通过 | |
| 236 | - redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), param.getStream(), streamAuthorityInfo); | |
| 237 | - } | |
| 238 | - } else { | |
| 239 | - zlmMediaListManager.sendStreamEvent(param.getApp(), param.getStream(), param.getMediaServerId()); | |
| 240 | - } | |
| 241 | - | |
| 242 | - | |
| 243 | - HookResultForOnPublish result = HookResultForOnPublish.SUCCESS(); | |
| 244 | - result.setEnable_audio(true); | |
| 245 | - taskExecutor.execute(() -> { | |
| 246 | - ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_publish, json); | |
| 247 | - if (subscribe != null) { | |
| 248 | - if (mediaInfo != null) { | |
| 249 | - subscribe.response(mediaInfo, param); | |
| 250 | - } else { | |
| 251 | - new HookResultForOnPublish(1, "zlm not register"); | |
| 252 | - } | |
| 253 | - } | |
| 254 | - }); | |
| 255 | - | |
| 256 | - // 是否录像 | |
| 257 | - if ("rtp".equals(param.getApp())) { | |
| 258 | - result.setEnable_mp4(userSetting.getRecordSip()); | |
| 259 | - } else { | |
| 260 | - result.setEnable_mp4(userSetting.isRecordPushLive()); | |
| 261 | - } | |
| 262 | - // 国标流 | |
| 263 | - if ("rtp".equals(param.getApp()) ) { | |
| 264 | - | |
| 265 | - InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, param.getStream()); | |
| 266 | - | |
| 267 | - // 单端口模式下修改流 ID | |
| 268 | - if (!mediaInfo.isRtpEnable() && inviteInfo == null) { | |
| 269 | - String ssrc = String.format("%010d", Long.parseLong(param.getStream(), 16)); | |
| 270 | - inviteInfo = inviteStreamService.getInviteInfoBySSRC(ssrc); | |
| 271 | - if (inviteInfo != null) { | |
| 272 | - result.setStream_replace(inviteInfo.getStream()); | |
| 273 | - logger.info("[ZLM HOOK]推流鉴权 stream: {} 替换为 {}", param.getStream(), inviteInfo.getStream()); | |
| 274 | - } | |
| 275 | - } | |
| 276 | - | |
| 277 | - // 设置音频信息及录制信息 | |
| 278 | - List<SsrcTransaction> ssrcTransactionForAll = sessionManager.getSsrcTransactionForAll(null, null, null, param.getStream()); | |
| 279 | - if (ssrcTransactionForAll != null && ssrcTransactionForAll.size() == 1) { | |
| 280 | - | |
| 281 | - // 为录制国标模拟一个鉴权信息, 方便后续写入录像文件时使用 | |
| 282 | - StreamAuthorityInfo streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(param); | |
| 283 | - streamAuthorityInfo.setApp(param.getApp()); | |
| 284 | - streamAuthorityInfo.setStream(ssrcTransactionForAll.get(0).getStream()); | |
| 285 | - streamAuthorityInfo.setCallId(ssrcTransactionForAll.get(0).getSipTransactionInfo().getCallId()); | |
| 286 | - | |
| 287 | - redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), ssrcTransactionForAll.get(0).getStream(), streamAuthorityInfo); | |
| 288 | - | |
| 289 | - String deviceId = ssrcTransactionForAll.get(0).getDeviceId(); | |
| 290 | - String channelId = ssrcTransactionForAll.get(0).getChannelId(); | |
| 291 | - DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); | |
| 292 | - if (deviceChannel != null) { | |
| 293 | - result.setEnable_audio(deviceChannel.isHasAudio()); | |
| 294 | - } | |
| 295 | - // 如果是录像下载就设置视频间隔十秒 | |
| 296 | - if (ssrcTransactionForAll.get(0).getType() == InviteSessionType.DOWNLOAD) { | |
| 297 | - // 获取录像的总时长,然后设置为这个视频的时长 | |
| 298 | - InviteInfo inviteInfoForDownload = inviteStreamService.getInviteInfo(InviteSessionType.DOWNLOAD, deviceId, channelId, param.getStream()); | |
| 299 | - if (inviteInfoForDownload != null && inviteInfoForDownload.getStreamInfo() != null) { | |
| 300 | - String startTime = inviteInfoForDownload.getStreamInfo().getStartTime(); | |
| 301 | - String endTime = inviteInfoForDownload.getStreamInfo().getEndTime(); | |
| 302 | - long difference = DateUtil.getDifference(startTime, endTime) / 1000; | |
| 303 | - result.setMp4_max_second((int) difference); | |
| 304 | - result.setEnable_mp4(true); | |
| 305 | - // 设置为2保证得到的mp4的时长是正常的 | |
| 306 | - result.setModify_stamp(2); | |
| 307 | - } | |
| 308 | - } | |
| 309 | - } | |
| 310 | - } | |
| 311 | - if (param.getApp().equalsIgnoreCase("rtp")) { | |
| 312 | - String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_" + param.getStream(); | |
| 313 | - OtherRtpSendInfo otherRtpSendInfo = (OtherRtpSendInfo)redisTemplate.opsForValue().get(receiveKey); | |
| 314 | - | |
| 315 | - String receiveKeyForPS = VideoManagerConstants.WVP_OTHER_RECEIVE_PS_INFO + userSetting.getServerId() + "_" + param.getStream(); | |
| 316 | - OtherPsSendInfo otherPsSendInfo = (OtherPsSendInfo)redisTemplate.opsForValue().get(receiveKeyForPS); | |
| 317 | - if (otherRtpSendInfo != null || otherPsSendInfo != null) { | |
| 318 | - result.setEnable_mp4(true); | |
| 319 | - } | |
| 320 | - } | |
| 321 | - logger.info("[ZLM HOOK]推流鉴权 响应:{}->{}->>>>{}", param.getMediaServerId(), param, result); | |
| 322 | - return result; | |
| 323 | - } | |
| 324 | - | |
| 325 | - | |
| 326 | - /** | |
| 327 | - * rtsp/rtmp流注册或注销时触发此事件;此事件对回复不敏感。 | |
| 328 | - */ | |
| 329 | - @ResponseBody | |
| 330 | - @PostMapping(value = "/on_stream_changed", produces = "application/json;charset=UTF-8") | |
| 331 | - public HookResult onStreamChanged(@RequestBody OnStreamChangedHookParam param) { | |
| 332 | - | |
| 333 | - if (param.isRegist()) { | |
| 334 | - logger.info("[ZLM HOOK] 流注册, {}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); | |
| 335 | - } else { | |
| 336 | - logger.info("[ZLM HOOK] 流注销, {}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); | |
| 337 | - } | |
| 338 | - | |
| 339 | - | |
| 340 | - JSONObject json = (JSONObject) JSON.toJSON(param); | |
| 341 | - taskExecutor.execute(() -> { | |
| 342 | - ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_stream_changed, json); | |
| 343 | - MediaServerItem mediaInfo = mediaServerService.getOne(param.getMediaServerId()); | |
| 344 | - if (mediaInfo == null) { | |
| 345 | - logger.info("[ZLM HOOK] 流变化未找到ZLM, {}", param.getMediaServerId()); | |
| 346 | - return; | |
| 347 | - } | |
| 348 | - if (subscribe != null) { | |
| 349 | - subscribe.response(mediaInfo, param); | |
| 350 | - } | |
| 351 | - | |
| 352 | - List<OnStreamChangedHookParam.MediaTrack> tracks = param.getTracks(); | |
| 353 | - // TODO 重构此处逻辑 | |
| 354 | - if (param.isRegist()) { | |
| 355 | - // 处理流注册的鉴权信息, 流注销这里不再删除鉴权信息,下次来了新的鉴权信息会对就的进行覆盖 | |
| 356 | - if (param.getOriginType() == OriginType.RTMP_PUSH.ordinal() | |
| 357 | - || param.getOriginType() == OriginType.RTSP_PUSH.ordinal() | |
| 358 | - || param.getOriginType() == OriginType.RTC_PUSH.ordinal()) { | |
| 359 | - StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream()); | |
| 360 | - if (streamAuthorityInfo == null) { | |
| 361 | - streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(param); | |
| 362 | - } else { | |
| 363 | - streamAuthorityInfo.setOriginType(param.getOriginType()); | |
| 364 | - streamAuthorityInfo.setOriginTypeStr(param.getOriginTypeStr()); | |
| 365 | - } | |
| 366 | - redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), param.getStream(), streamAuthorityInfo); | |
| 367 | - } | |
| 368 | - } | |
| 369 | - | |
| 370 | - if ("rtsp".equals(param.getSchema())) { | |
| 371 | - // 更新流媒体负载信息 | |
| 372 | - if (param.isRegist()) { | |
| 373 | - mediaServerService.addCount(param.getMediaServerId()); | |
| 374 | - } else { | |
| 375 | - mediaServerService.removeCount(param.getMediaServerId()); | |
| 376 | - } | |
| 377 | - // 设置拉流代理上线/离线 | |
| 378 | - int updateStatusResult = streamProxyService.updateStatus(param.isRegist(), param.getApp(), param.getStream()); | |
| 379 | - if (updateStatusResult > 0) { | |
| 380 | - | |
| 381 | - } | |
| 382 | - | |
| 383 | - if ("rtp".equals(param.getApp()) && !param.isRegist()) { | |
| 384 | - InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, param.getStream()); | |
| 385 | - if (inviteInfo != null && (inviteInfo.getType() == InviteSessionType.PLAY || inviteInfo.getType() == InviteSessionType.PLAYBACK)) { | |
| 386 | - inviteStreamService.removeInviteInfo(inviteInfo); | |
| 387 | - storager.stopPlay(inviteInfo.getDeviceId(), inviteInfo.getChannelId()); | |
| 388 | - } | |
| 389 | - } else { | |
| 390 | - if (!"rtp".equals(param.getApp())) { | |
| 391 | - String type = OriginType.values()[param.getOriginType()].getType(); | |
| 392 | - if (param.isRegist()) { | |
| 393 | - StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo( | |
| 394 | - param.getApp(), param.getStream()); | |
| 395 | - String callId = null; | |
| 396 | - if (streamAuthorityInfo != null) { | |
| 397 | - callId = streamAuthorityInfo.getCallId(); | |
| 398 | - } | |
| 399 | - StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaInfo, | |
| 400 | - param.getApp(), param.getStream(), tracks, callId); | |
| 401 | - param.setStreamInfo(new StreamContent(streamInfoByAppAndStream)); | |
| 402 | - redisCatchStorage.addStream(mediaInfo, type, param.getApp(), param.getStream(), param); | |
| 403 | - if (param.getOriginType() == OriginType.RTSP_PUSH.ordinal() | |
| 404 | - || param.getOriginType() == OriginType.RTMP_PUSH.ordinal() | |
| 405 | - || param.getOriginType() == OriginType.RTC_PUSH.ordinal()) { | |
| 406 | - param.setSeverId(userSetting.getServerId()); | |
| 407 | - zlmMediaListManager.addPush(param); | |
| 408 | - | |
| 409 | - // 冗余数据,自己系统中自用 | |
| 410 | - redisCatchStorage.addPushListItem(param.getApp(), param.getStream(), param); | |
| 411 | - } | |
| 412 | - } else { | |
| 413 | - // 兼容流注销时类型从redis记录获取 | |
| 414 | - OnStreamChangedHookParam onStreamChangedHookParam = redisCatchStorage.getStreamInfo( | |
| 415 | - param.getApp(), param.getStream(), param.getMediaServerId()); | |
| 416 | - if (onStreamChangedHookParam != null) { | |
| 417 | - type = OriginType.values()[onStreamChangedHookParam.getOriginType()].getType(); | |
| 418 | - redisCatchStorage.removeStream(mediaInfo.getId(), type, param.getApp(), param.getStream()); | |
| 419 | - if ("PUSH".equalsIgnoreCase(type)) { | |
| 420 | - // 冗余数据,自己系统中自用 | |
| 421 | - redisCatchStorage.removePushListItem(param.getApp(), param.getStream(), param.getMediaServerId()); | |
| 422 | - } | |
| 423 | - } | |
| 424 | - GbStream gbStream = storager.getGbStream(param.getApp(), param.getStream()); | |
| 425 | - if (gbStream != null) { | |
| 426 | -// eventPublisher.catalogEventPublishForStream(null, gbStream, CatalogEvent.OFF); | |
| 427 | - } | |
| 428 | - zlmMediaListManager.removeMedia(param.getApp(), param.getStream()); | |
| 429 | - } | |
| 430 | - GbStream gbStream = storager.getGbStream(param.getApp(), param.getStream()); | |
| 431 | - if (gbStream != null) { | |
| 432 | - if (userSetting.isUsePushingAsStatus()) { | |
| 433 | - eventPublisher.catalogEventPublishForStream(null, gbStream, param.isRegist()?CatalogEvent.ON:CatalogEvent.OFF); | |
| 434 | - } | |
| 435 | - } | |
| 436 | - if (type != null) { | |
| 437 | - // 发送流变化redis消息 | |
| 438 | - JSONObject jsonObject = new JSONObject(); | |
| 439 | - jsonObject.put("serverId", userSetting.getServerId()); | |
| 440 | - jsonObject.put("app", param.getApp()); | |
| 441 | - jsonObject.put("stream", param.getStream()); | |
| 442 | - jsonObject.put("register", param.isRegist()); | |
| 443 | - jsonObject.put("mediaServerId", param.getMediaServerId()); | |
| 444 | - redisCatchStorage.sendStreamChangeMsg(type, jsonObject); | |
| 445 | - } | |
| 446 | - } | |
| 447 | - } | |
| 448 | - if (!param.isRegist()) { | |
| 449 | - List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByStream(param.getStream()); | |
| 450 | - if (!sendRtpItems.isEmpty()) { | |
| 451 | - for (SendRtpItem sendRtpItem : sendRtpItems) { | |
| 452 | - if (sendRtpItem != null && sendRtpItem.getApp().equals(param.getApp())) { | |
| 453 | - String platformId = sendRtpItem.getPlatformId(); | |
| 454 | - ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId); | |
| 455 | - Device device = deviceService.getDevice(platformId); | |
| 456 | - | |
| 457 | - try { | |
| 458 | - if (platform != null) { | |
| 459 | - commanderFroPlatform.streamByeCmd(platform, sendRtpItem); | |
| 460 | - redisCatchStorage.deleteSendRTPServer(platformId, sendRtpItem.getChannelId(), | |
| 461 | - sendRtpItem.getCallId(), sendRtpItem.getStreamId()); | |
| 462 | - } else { | |
| 463 | - cmder.streamByeCmd(device, sendRtpItem.getChannelId(), param.getStream(), sendRtpItem.getCallId()); | |
| 464 | - } | |
| 465 | - } catch (SipException | InvalidArgumentException | ParseException | | |
| 466 | - SsrcTransactionNotFoundException e) { | |
| 467 | - logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage()); | |
| 468 | - } | |
| 469 | - } | |
| 470 | - } | |
| 471 | - } | |
| 472 | - } | |
| 473 | - } | |
| 474 | - }); | |
| 475 | - | |
| 476 | - return HookResult.SUCCESS(); | |
| 477 | - } | |
| 478 | - | |
| 479 | - /** | |
| 480 | - * 流无人观看时事件,用户可以通过此事件选择是否关闭无人看的流。 | |
| 481 | - */ | |
| 482 | - @ResponseBody | |
| 483 | - @PostMapping(value = "/on_stream_none_reader", produces = "application/json;charset=UTF-8") | |
| 484 | - public JSONObject onStreamNoneReader(@RequestBody OnStreamNoneReaderHookParam param) { | |
| 485 | - | |
| 486 | - logger.info("[ZLM HOOK]流无人观看:{}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), | |
| 487 | - param.getApp(), param.getStream()); | |
| 488 | - JSONObject ret = new JSONObject(); | |
| 489 | - ret.put("code", 0); | |
| 490 | - // 国标类型的流 | |
| 491 | - if ("rtp".equals(param.getApp())) { | |
| 492 | - ret.put("close", userSetting.getStreamOnDemand()); | |
| 493 | - // 国标流, 点播/录像回放/录像下载 | |
| 494 | - InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, param.getStream()); | |
| 495 | - // 点播 | |
| 496 | - if (inviteInfo != null) { | |
| 497 | - // 录像下载 | |
| 498 | - if (inviteInfo.getType() == InviteSessionType.DOWNLOAD) { | |
| 499 | - ret.put("close", false); | |
| 500 | - return ret; | |
| 501 | - } | |
| 502 | - // 收到无人观看说明流也没有在往上级推送 | |
| 503 | - if (redisCatchStorage.isChannelSendingRTP(inviteInfo.getChannelId())) { | |
| 504 | - List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByChnnelId( | |
| 505 | - inviteInfo.getChannelId()); | |
| 506 | - if (sendRtpItems.size() > 0) { | |
| 507 | - for (SendRtpItem sendRtpItem : sendRtpItems) { | |
| 508 | - ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId()); | |
| 509 | - try { | |
| 510 | - commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId()); | |
| 511 | - } catch (SipException | InvalidArgumentException | ParseException e) { | |
| 512 | - logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage()); | |
| 513 | - } | |
| 514 | - redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(), | |
| 515 | - sendRtpItem.getCallId(), sendRtpItem.getStreamId()); | |
| 516 | - if (InviteStreamType.PUSH == sendRtpItem.getPlayType()) { | |
| 517 | - MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, | |
| 518 | - sendRtpItem.getApp(), sendRtpItem.getStreamId(), sendRtpItem.getChannelId(), | |
| 519 | - sendRtpItem.getPlatformId(), parentPlatform.getName(), userSetting.getServerId(), sendRtpItem.getMediaServerId()); | |
| 520 | - messageForPushChannel.setPlatFormIndex(parentPlatform.getId()); | |
| 521 | - redisCatchStorage.sendPlatformStopPlayMsg(messageForPushChannel); | |
| 522 | - } | |
| 523 | - } | |
| 524 | - } | |
| 525 | - } | |
| 526 | - Device device = deviceService.getDevice(inviteInfo.getDeviceId()); | |
| 527 | - if (device != null) { | |
| 528 | - try { | |
| 529 | - // 多查询一次防止已经被处理了 | |
| 530 | - InviteInfo info = inviteStreamService.getInviteInfo(inviteInfo.getType(), | |
| 531 | - inviteInfo.getDeviceId(), inviteInfo.getChannelId(), inviteInfo.getStream()); | |
| 532 | - if (info != null) { | |
| 533 | - cmder.streamByeCmd(device, inviteInfo.getChannelId(), | |
| 534 | - inviteInfo.getStream(), null); | |
| 535 | - }else { | |
| 536 | - logger.info("[无人观看] 未找到设备的点播信息: {}, 流:{}", inviteInfo.getDeviceId(), param.getStream()); | |
| 537 | - } | |
| 538 | - } catch (InvalidArgumentException | ParseException | SipException | | |
| 539 | - SsrcTransactionNotFoundException e) { | |
| 540 | - logger.error("[无人观看]点播, 发送BYE失败 {}", e.getMessage()); | |
| 541 | - } | |
| 542 | - }else { | |
| 543 | - logger.info("[无人观看] 未找到设备: {},流:{}", inviteInfo.getDeviceId(), param.getStream()); | |
| 544 | - } | |
| 545 | - | |
| 546 | - inviteStreamService.removeInviteInfo(inviteInfo.getType(), inviteInfo.getDeviceId(), | |
| 547 | - inviteInfo.getChannelId(), inviteInfo.getStream()); | |
| 548 | - storager.stopPlay(inviteInfo.getDeviceId(), inviteInfo.getChannelId()); | |
| 549 | - return ret; | |
| 550 | - } | |
| 551 | - } else { | |
| 552 | - // 非国标流 推流/拉流代理 | |
| 553 | - // 拉流代理 | |
| 554 | - StreamProxyItem streamProxyItem = streamProxyService.getStreamProxyByAppAndStream(param.getApp(), param.getStream()); | |
| 555 | - if (streamProxyItem != null) { | |
| 556 | - if (streamProxyItem.isEnableRemoveNoneReader()) { | |
| 557 | - // 无人观看自动移除 | |
| 558 | - ret.put("close", true); | |
| 559 | - streamProxyService.del(param.getApp(), param.getStream()); | |
| 560 | - String url = streamProxyItem.getUrl() != null ? streamProxyItem.getUrl() : streamProxyItem.getSrcUrl(); | |
| 561 | - logger.info("[{}/{}]<-[{}] 拉流代理无人观看已经移除", param.getApp(), param.getStream(), url); | |
| 562 | - } else if (streamProxyItem.isEnableDisableNoneReader()) { | |
| 563 | - // 无人观看停用 | |
| 564 | - ret.put("close", true); | |
| 565 | - // 修改数据 | |
| 566 | - streamProxyService.stop(param.getApp(), param.getStream()); | |
| 567 | - } else { | |
| 568 | - // 无人观看不做处理 | |
| 569 | - ret.put("close", false); | |
| 570 | - } | |
| 571 | - return ret; | |
| 572 | - } | |
| 573 | - // TODO 推流具有主动性,暂时不做处理 | |
| 574 | -// StreamPushItem streamPushItem = streamPushService.getPush(app, streamId); | |
| 575 | -// if (streamPushItem != null) { | |
| 576 | -// // TODO 发送停止 | |
| 577 | -// | |
| 578 | -// } | |
| 579 | - } | |
| 580 | - return ret; | |
| 581 | - } | |
| 582 | - | |
| 583 | - /** | |
| 584 | - * 流未找到事件,用户可以在此事件触发时,立即去拉流,这样可以实现按需拉流;此事件对回复不敏感。 | |
| 585 | - */ | |
| 586 | - @ResponseBody | |
| 587 | - @PostMapping(value = "/on_stream_not_found", produces = "application/json;charset=UTF-8") | |
| 588 | - public DeferredResult<HookResult> onStreamNotFound(@RequestBody OnStreamNotFoundHookParam param) { | |
| 589 | - logger.info("[ZLM HOOK] 流未找到:{}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); | |
| 590 | - | |
| 591 | - DeferredResult<HookResult> defaultResult = new DeferredResult<>(); | |
| 592 | - | |
| 593 | - MediaServerItem mediaInfo = mediaServerService.getOne(param.getMediaServerId()); | |
| 594 | - if (!userSetting.isAutoApplyPlay() || mediaInfo == null) { | |
| 595 | - defaultResult.setResult(new HookResult(ErrorCode.ERROR404.getCode(), ErrorCode.ERROR404.getMsg())); | |
| 596 | - return defaultResult; | |
| 597 | - } | |
| 598 | - | |
| 599 | - if ("rtp".equals(param.getApp())) { | |
| 600 | - String[] s = param.getStream().split("_"); | |
| 601 | - if ((s.length != 2 && s.length != 4)) { | |
| 602 | - defaultResult.setResult(HookResult.SUCCESS()); | |
| 603 | - return defaultResult; | |
| 604 | - } | |
| 605 | - String deviceId = s[0]; | |
| 606 | - String channelId = s[1]; | |
| 607 | - Device device = redisCatchStorage.getDevice(deviceId); | |
| 608 | - if (device == null || !device.isOnLine()) { | |
| 609 | - defaultResult.setResult(new HookResult(ErrorCode.ERROR404.getCode(), ErrorCode.ERROR404.getMsg())); | |
| 610 | - return defaultResult; | |
| 611 | - } | |
| 612 | - DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); | |
| 613 | - if (deviceChannel == null) { | |
| 614 | - defaultResult.setResult(new HookResult(ErrorCode.ERROR404.getCode(), ErrorCode.ERROR404.getMsg())); | |
| 615 | - return defaultResult; | |
| 616 | - } | |
| 617 | - if (s.length == 2) { | |
| 618 | - logger.info("[ZLM HOOK] 预览流未找到, 发起自动点播:{}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); | |
| 619 | - | |
| 620 | - RequestMessage msg = new RequestMessage(); | |
| 621 | - String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId; | |
| 622 | - boolean exist = resultHolder.exist(key, null); | |
| 623 | - msg.setKey(key); | |
| 624 | - String uuid = UUID.randomUUID().toString(); | |
| 625 | - msg.setId(uuid); | |
| 626 | - DeferredResult<HookResult> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue()); | |
| 627 | - | |
| 628 | - result.onTimeout(() -> { | |
| 629 | - logger.info("[ZLM HOOK] 预览流自动点播, 等待超时"); | |
| 630 | - msg.setData(new HookResult(ErrorCode.ERROR100.getCode(), "点播超时")); | |
| 631 | - resultHolder.invokeAllResult(msg); | |
| 632 | - inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); | |
| 633 | - storager.stopPlay(deviceId, channelId); | |
| 634 | - }); | |
| 635 | - | |
| 636 | - resultHolder.put(key, uuid, result); | |
| 637 | - | |
| 638 | - if (!exist) { | |
| 639 | - playService.play(mediaInfo, deviceId, channelId, null, (code, message, data) -> { | |
| 640 | - msg.setData(new HookResult(code, message)); | |
| 641 | - resultHolder.invokeResult(msg); | |
| 642 | - }); | |
| 643 | - } | |
| 644 | - return result; | |
| 645 | - }else if(s.length == 4){ | |
| 646 | - // 此时为录像回放, 录像回放格式为> 设备ID_通道ID_开始时间_结束时间 | |
| 647 | - String startTimeStr = s[2]; | |
| 648 | - String endTimeStr = s[3]; | |
| 649 | - if (startTimeStr == null || endTimeStr == null || startTimeStr.length() != 14 || endTimeStr.length() != 14) { | |
| 650 | - defaultResult.setResult(HookResult.SUCCESS()); | |
| 651 | - return defaultResult; | |
| 652 | - } | |
| 653 | - String startTime = DateUtil.urlToyyyy_MM_dd_HH_mm_ss(startTimeStr); | |
| 654 | - String endTime = DateUtil.urlToyyyy_MM_dd_HH_mm_ss(endTimeStr); | |
| 655 | - logger.info("[ZLM HOOK] 回放流未找到, 发起自动点播:{}->{}->{}/{}-{}-{}", | |
| 656 | - param.getMediaServerId(), param.getSchema(), | |
| 657 | - param.getApp(), param.getStream(), | |
| 658 | - startTime, endTime | |
| 659 | - ); | |
| 660 | - RequestMessage msg = new RequestMessage(); | |
| 661 | - String key = DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId; | |
| 662 | - boolean exist = resultHolder.exist(key, null); | |
| 663 | - msg.setKey(key); | |
| 664 | - String uuid = UUID.randomUUID().toString(); | |
| 665 | - msg.setId(uuid); | |
| 666 | - DeferredResult<HookResult> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue()); | |
| 667 | - | |
| 668 | - result.onTimeout(() -> { | |
| 669 | - logger.info("[ZLM HOOK] 回放流自动点播, 等待超时"); | |
| 670 | - // 释放rtpserver | |
| 671 | - msg.setData(new HookResult(ErrorCode.ERROR100.getCode(), "点播超时")); | |
| 672 | - resultHolder.invokeResult(msg); | |
| 673 | - }); | |
| 674 | - | |
| 675 | - resultHolder.put(key, uuid, result); | |
| 676 | - | |
| 677 | - if (!exist) { | |
| 678 | - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaInfo, param.getStream(), null, | |
| 679 | - device.isSsrcCheck(), true, 0, false, device.getStreamModeForParam()); | |
| 680 | - playService.playBack(mediaInfo, ssrcInfo, deviceId, channelId, startTime, endTime, (code, message, data) -> { | |
| 681 | - msg.setData(new HookResult(code, message)); | |
| 682 | - resultHolder.invokeResult(msg); | |
| 683 | - }); | |
| 684 | - } | |
| 685 | - return result; | |
| 686 | - }else { | |
| 687 | - defaultResult.setResult(HookResult.SUCCESS()); | |
| 688 | - return defaultResult; | |
| 689 | - } | |
| 690 | - | |
| 691 | - } else { | |
| 692 | - // 拉流代理 | |
| 693 | - StreamProxyItem streamProxyByAppAndStream = streamProxyService.getStreamProxyByAppAndStream(param.getApp(), param.getStream()); | |
| 694 | - if (streamProxyByAppAndStream != null && streamProxyByAppAndStream.isEnableDisableNoneReader()) { | |
| 695 | - streamProxyService.start(param.getApp(), param.getStream()); | |
| 696 | - } | |
| 697 | - DeferredResult<HookResult> result = new DeferredResult<>(); | |
| 698 | - result.setResult(HookResult.SUCCESS()); | |
| 699 | - return result; | |
| 700 | - } | |
| 701 | - } | |
| 702 | - | |
| 703 | - /** | |
| 704 | - * 服务器启动事件,可以用于监听服务器崩溃重启;此事件对回复不敏感。 | |
| 705 | - */ | |
| 706 | - @ResponseBody | |
| 707 | - @PostMapping(value = "/on_server_started", produces = "application/json;charset=UTF-8") | |
| 708 | - public HookResult onServerStarted(HttpServletRequest request, @RequestBody JSONObject jsonObject) { | |
| 709 | - | |
| 710 | - jsonObject.put("ip", request.getRemoteAddr()); | |
| 711 | - ZLMServerConfig zlmServerConfig = JSON.to(ZLMServerConfig.class, jsonObject); | |
| 712 | - zlmServerConfig.setIp(request.getRemoteAddr()); | |
| 713 | - logger.info("[ZLM HOOK] zlm 启动 " + zlmServerConfig.getGeneralMediaServerId()); | |
| 714 | - taskExecutor.execute(() -> { | |
| 715 | - List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_started); | |
| 716 | - if (subscribes != null && subscribes.size() > 0) { | |
| 717 | - for (ZlmHttpHookSubscribe.Event subscribe : subscribes) { | |
| 718 | - subscribe.response(null, zlmServerConfig); | |
| 719 | - } | |
| 720 | - } | |
| 721 | - mediaServerService.zlmServerOnline(zlmServerConfig); | |
| 722 | - }); | |
| 723 | - | |
| 724 | - return HookResult.SUCCESS(); | |
| 725 | - } | |
| 726 | - | |
| 727 | - /** | |
| 728 | - * 发送rtp(startSendRtp)被动关闭时回调 | |
| 729 | - */ | |
| 730 | - @ResponseBody | |
| 731 | - @PostMapping(value = "/on_send_rtp_stopped", produces = "application/json;charset=UTF-8") | |
| 732 | - public HookResult onSendRtpStopped(HttpServletRequest request, @RequestBody OnSendRtpStoppedHookParam param) { | |
| 733 | - | |
| 734 | - logger.info("[ZLM HOOK] rtp发送关闭:{}->{}/{}", param.getMediaServerId(), param.getApp(), param.getStream()); | |
| 735 | - | |
| 736 | - // 查找对应的上级推流,发送停止 | |
| 737 | - if (!"rtp".equals(param.getApp())) { | |
| 738 | - return HookResult.SUCCESS(); | |
| 739 | - } | |
| 740 | - taskExecutor.execute(() -> { | |
| 741 | - List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByStream(param.getStream()); | |
| 742 | - if (sendRtpItems.size() > 0) { | |
| 743 | - for (SendRtpItem sendRtpItem : sendRtpItems) { | |
| 744 | - ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId()); | |
| 745 | - ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrc()); | |
| 746 | - try { | |
| 747 | - commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId()); | |
| 748 | - } catch (SipException | InvalidArgumentException | ParseException e) { | |
| 749 | - logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage()); | |
| 750 | - } | |
| 751 | - redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(), | |
| 752 | - sendRtpItem.getCallId(), sendRtpItem.getStreamId()); | |
| 753 | - } | |
| 754 | - } | |
| 755 | - }); | |
| 756 | - | |
| 757 | - return HookResult.SUCCESS(); | |
| 758 | - } | |
| 759 | - | |
| 760 | - /** | |
| 761 | - * rtpServer收流超时 | |
| 762 | - */ | |
| 763 | - @ResponseBody | |
| 764 | - @PostMapping(value = "/on_rtp_server_timeout", produces = "application/json;charset=UTF-8") | |
| 765 | - public HookResult onRtpServerTimeout(HttpServletRequest request, @RequestBody OnRtpServerTimeoutHookParam param) { | |
| 766 | - logger.info("[ZLM HOOK] rtpServer收流超时:{}->{}({})", param.getMediaServerId(), param.getStream_id(), param.getSsrc()); | |
| 767 | - | |
| 768 | - taskExecutor.execute(() -> { | |
| 769 | - JSONObject json = (JSONObject) JSON.toJSON(param); | |
| 770 | - List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_rtp_server_timeout); | |
| 771 | - if (subscribes != null && !subscribes.isEmpty()) { | |
| 772 | - for (ZlmHttpHookSubscribe.Event subscribe : subscribes) { | |
| 773 | - subscribe.response(null, param); | |
| 774 | - } | |
| 775 | - } | |
| 776 | - }); | |
| 777 | - | |
| 778 | - return HookResult.SUCCESS(); | |
| 779 | - } | |
| 780 | - | |
| 781 | - /** | |
| 782 | - * 录像完成事件 | |
| 783 | - */ | |
| 784 | - @ResponseBody | |
| 785 | - @PostMapping(value = "/on_record_mp4", produces = "application/json;charset=UTF-8") | |
| 786 | - public HookResult onRecordMp4(HttpServletRequest request, @RequestBody OnRecordMp4HookParam param) { | |
| 787 | - logger.info("[ZLM HOOK] 录像完成事件:{}->{}", param.getMediaServerId(), param.getFile_path()); | |
| 788 | - | |
| 789 | - taskExecutor.execute(() -> { | |
| 790 | - List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_record_mp4); | |
| 791 | - if (subscribes != null && !subscribes.isEmpty()) { | |
| 792 | - for (ZlmHttpHookSubscribe.Event subscribe : subscribes) { | |
| 793 | - subscribe.response(null, param); | |
| 794 | - } | |
| 795 | - } | |
| 796 | - cloudRecordService.addRecord(param); | |
| 797 | - | |
| 798 | - }); | |
| 799 | - | |
| 800 | - return HookResult.SUCCESS(); | |
| 801 | - } | |
| 802 | - | |
| 803 | - private Map<String, String> urlParamToMap(String params) { | |
| 804 | - HashMap<String, String> map = new HashMap<>(); | |
| 805 | - if (ObjectUtils.isEmpty(params)) { | |
| 806 | - return map; | |
| 807 | - } | |
| 808 | - String[] paramsArray = params.split("&"); | |
| 809 | - if (paramsArray.length == 0) { | |
| 810 | - return map; | |
| 811 | - } | |
| 812 | - for (String param : paramsArray) { | |
| 813 | - String[] paramArray = param.split("="); | |
| 814 | - if (paramArray.length == 2) { | |
| 815 | - map.put(paramArray[0], paramArray[1]); | |
| 816 | - } | |
| 817 | - } | |
| 818 | - return map; | |
| 819 | - } | |
| 820 | -} | |
| 1 | +package com.genersoft.iot.vmp.media.zlm; | |
| 2 | + | |
| 3 | +import com.alibaba.fastjson2.JSON; | |
| 4 | +import com.alibaba.fastjson2.JSONObject; | |
| 5 | +import com.genersoft.iot.vmp.common.InviteInfo; | |
| 6 | +import com.genersoft.iot.vmp.common.InviteSessionType; | |
| 7 | +import com.genersoft.iot.vmp.common.StreamInfo; | |
| 8 | +import com.genersoft.iot.vmp.common.VideoManagerConstants; | |
| 9 | +import com.genersoft.iot.vmp.conf.UserSetting; | |
| 10 | +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; | |
| 11 | +import com.genersoft.iot.vmp.gb28181.bean.*; | |
| 12 | +import com.genersoft.iot.vmp.gb28181.event.EventPublisher; | |
| 13 | +import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; | |
| 14 | +import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; | |
| 15 | +import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; | |
| 16 | +import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | |
| 17 | +import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; | |
| 18 | +import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; | |
| 19 | +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; | |
| 20 | +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | |
| 21 | +import com.genersoft.iot.vmp.media.zlm.dto.HookType; | |
| 22 | +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | |
| 23 | +import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; | |
| 24 | +import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; | |
| 25 | +import com.genersoft.iot.vmp.media.zlm.dto.hook.*; | |
| 26 | +import com.genersoft.iot.vmp.service.*; | |
| 27 | +import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; | |
| 28 | +import com.genersoft.iot.vmp.service.bean.SSRCInfo; | |
| 29 | +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | |
| 30 | +import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | |
| 31 | +import com.genersoft.iot.vmp.utils.DateUtil; | |
| 32 | +import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; | |
| 33 | +import com.genersoft.iot.vmp.vmanager.bean.OtherPsSendInfo; | |
| 34 | +import com.genersoft.iot.vmp.vmanager.bean.OtherRtpSendInfo; | |
| 35 | +import com.genersoft.iot.vmp.vmanager.bean.StreamContent; | |
| 36 | +import org.slf4j.Logger; | |
| 37 | +import org.slf4j.LoggerFactory; | |
| 38 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 39 | +import org.springframework.beans.factory.annotation.Qualifier; | |
| 40 | +import org.springframework.data.redis.core.RedisTemplate; | |
| 41 | +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; | |
| 42 | +import org.springframework.util.ObjectUtils; | |
| 43 | +import org.springframework.web.bind.annotation.*; | |
| 44 | +import org.springframework.web.context.request.async.DeferredResult; | |
| 45 | + | |
| 46 | +import javax.servlet.http.HttpServletRequest; | |
| 47 | +import javax.sip.InvalidArgumentException; | |
| 48 | +import javax.sip.SipException; | |
| 49 | +import java.text.ParseException; | |
| 50 | +import java.util.HashMap; | |
| 51 | +import java.util.List; | |
| 52 | +import java.util.Map; | |
| 53 | +import java.util.UUID; | |
| 54 | + | |
| 55 | +/** | |
| 56 | + * @description:针对 ZLMediaServer的hook事件监听 | |
| 57 | + * @author: swwheihei | |
| 58 | + * @date: 2020年5月8日 上午10:46:48 | |
| 59 | + */ | |
| 60 | +@RestController | |
| 61 | +@RequestMapping("/index/hook") | |
| 62 | +public class ZLMHttpHookListener { | |
| 63 | + | |
| 64 | + private final static Logger logger = LoggerFactory.getLogger(ZLMHttpHookListener.class); | |
| 65 | + | |
| 66 | + @Autowired | |
| 67 | + private SIPCommander cmder; | |
| 68 | + | |
| 69 | + @Autowired | |
| 70 | + private ISIPCommanderForPlatform commanderFroPlatform; | |
| 71 | + | |
| 72 | + @Autowired | |
| 73 | + private AudioBroadcastManager audioBroadcastManager; | |
| 74 | + | |
| 75 | + @Autowired | |
| 76 | + private ZLMServerFactory zlmServerFactory; | |
| 77 | + | |
| 78 | + @Autowired | |
| 79 | + private IPlayService playService; | |
| 80 | + | |
| 81 | + @Autowired | |
| 82 | + private IVideoManagerStorage storager; | |
| 83 | + | |
| 84 | + @Autowired | |
| 85 | + private IRedisCatchStorage redisCatchStorage; | |
| 86 | + | |
| 87 | + @Autowired | |
| 88 | + private IInviteStreamService inviteStreamService; | |
| 89 | + | |
| 90 | + @Autowired | |
| 91 | + private IDeviceService deviceService; | |
| 92 | + | |
| 93 | + @Autowired | |
| 94 | + private IMediaServerService mediaServerService; | |
| 95 | + | |
| 96 | + @Autowired | |
| 97 | + private IStreamProxyService streamProxyService; | |
| 98 | + | |
| 99 | + @Autowired | |
| 100 | + private DeferredResultHolder resultHolder; | |
| 101 | + | |
| 102 | + @Autowired | |
| 103 | + private IMediaService mediaService; | |
| 104 | + | |
| 105 | + @Autowired | |
| 106 | + private EventPublisher eventPublisher; | |
| 107 | + | |
| 108 | + @Autowired | |
| 109 | + private ZLMMediaListManager zlmMediaListManager; | |
| 110 | + | |
| 111 | + @Autowired | |
| 112 | + private ZlmHttpHookSubscribe subscribe; | |
| 113 | + | |
| 114 | + @Autowired | |
| 115 | + private UserSetting userSetting; | |
| 116 | + | |
| 117 | + @Autowired | |
| 118 | + private IUserService userService; | |
| 119 | + | |
| 120 | + @Autowired | |
| 121 | + private ICloudRecordService cloudRecordService; | |
| 122 | + | |
| 123 | + @Autowired | |
| 124 | + private VideoStreamSessionManager sessionManager; | |
| 125 | + | |
| 126 | + @Autowired | |
| 127 | + private AssistRESTfulUtils assistRESTfulUtils; | |
| 128 | + | |
| 129 | + @Autowired | |
| 130 | + private SSRCFactory ssrcFactory; | |
| 131 | + | |
| 132 | + @Qualifier("taskExecutor") | |
| 133 | + @Autowired | |
| 134 | + private ThreadPoolTaskExecutor taskExecutor; | |
| 135 | + | |
| 136 | + @Autowired | |
| 137 | + private RedisTemplate<Object, Object> redisTemplate; | |
| 138 | + | |
| 139 | + /** | |
| 140 | + * 服务器定时上报时间,上报间隔可配置,默认10s上报一次 | |
| 141 | + */ | |
| 142 | + @ResponseBody | |
| 143 | + | |
| 144 | + @PostMapping(value = "/on_server_keepalive", produces = "application/json;charset=UTF-8") | |
| 145 | + public HookResult onServerKeepalive(@RequestBody OnServerKeepaliveHookParam param) { | |
| 146 | + | |
| 147 | + | |
| 148 | + taskExecutor.execute(() -> { | |
| 149 | + List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_keepalive); | |
| 150 | + if (subscribes != null && subscribes.size() > 0) { | |
| 151 | + for (ZlmHttpHookSubscribe.Event subscribe : subscribes) { | |
| 152 | + subscribe.response(null, param); | |
| 153 | + } | |
| 154 | + } | |
| 155 | + }); | |
| 156 | + mediaServerService.updateMediaServerKeepalive(param.getMediaServerId(), param.getData()); | |
| 157 | + | |
| 158 | + return HookResult.SUCCESS(); | |
| 159 | + } | |
| 160 | + | |
| 161 | + /** | |
| 162 | + * 播放器鉴权事件,rtsp/rtmp/http-flv/ws-flv/hls的播放都将触发此鉴权事件。 | |
| 163 | + */ | |
| 164 | + @ResponseBody | |
| 165 | + | |
| 166 | + @PostMapping(value = "/on_play", produces = "application/json;charset=UTF-8") | |
| 167 | + public HookResult onPlay(@RequestBody OnPlayHookParam param) { | |
| 168 | + if (logger.isDebugEnabled()) { | |
| 169 | + logger.debug("[ZLM HOOK] 播放鉴权:{}->{}" + param.getMediaServerId(), param); | |
| 170 | + } | |
| 171 | + String mediaServerId = param.getMediaServerId(); | |
| 172 | + | |
| 173 | + taskExecutor.execute(() -> { | |
| 174 | + JSONObject json = (JSONObject) JSON.toJSON(param); | |
| 175 | + ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_play, json); | |
| 176 | + if (subscribe != null) { | |
| 177 | + MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); | |
| 178 | + if (mediaInfo != null) { | |
| 179 | + subscribe.response(mediaInfo, param); | |
| 180 | + } | |
| 181 | + } | |
| 182 | + }); | |
| 183 | + if (!"rtp".equals(param.getApp())) { | |
| 184 | + Map<String, String> paramMap = urlParamToMap(param.getParams()); | |
| 185 | + StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream()); | |
| 186 | + if (streamAuthorityInfo != null && streamAuthorityInfo.getCallId() != null && !streamAuthorityInfo.getCallId().equals(paramMap.get("callId"))) { | |
| 187 | + return new HookResult(401, "Unauthorized"); | |
| 188 | + } | |
| 189 | + } | |
| 190 | + | |
| 191 | + return HookResult.SUCCESS(); | |
| 192 | + } | |
| 193 | + | |
| 194 | + /** | |
| 195 | + * rtsp/rtmp/rtp推流鉴权事件。 | |
| 196 | + */ | |
| 197 | + @ResponseBody | |
| 198 | + @PostMapping(value = "/on_publish", produces = "application/json;charset=UTF-8") | |
| 199 | + public HookResultForOnPublish onPublish(@RequestBody OnPublishHookParam param) { | |
| 200 | + | |
| 201 | + JSONObject json = (JSONObject) JSON.toJSON(param); | |
| 202 | + | |
| 203 | + logger.info("[ZLM HOOK]推流鉴权:{}->{}", param.getMediaServerId(), param); | |
| 204 | + | |
| 205 | + String mediaServerId = json.getString("mediaServerId"); | |
| 206 | + MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); | |
| 207 | + if (mediaInfo == null) { | |
| 208 | + return new HookResultForOnPublish(200, "success"); | |
| 209 | + } | |
| 210 | + // 推流鉴权的处理 | |
| 211 | + if (!"rtp".equals(param.getApp())) { | |
| 212 | + StreamProxyItem stream = streamProxyService.getStreamProxyByAppAndStream(param.getApp(), param.getStream()); | |
| 213 | + if (stream != null) { | |
| 214 | + HookResultForOnPublish result = HookResultForOnPublish.SUCCESS(); | |
| 215 | + result.setEnable_audio(stream.isEnableAudio()); | |
| 216 | + result.setEnable_mp4(stream.isEnableMp4()); | |
| 217 | + return result; | |
| 218 | + } | |
| 219 | + if (userSetting.getPushAuthority()) { | |
| 220 | + // 推流鉴权 | |
| 221 | + if (param.getParams() == null) { | |
| 222 | + logger.info("推流鉴权失败: 缺少必要参数:sign=md5(user表的pushKey)"); | |
| 223 | + return new HookResultForOnPublish(401, "Unauthorized"); | |
| 224 | + } | |
| 225 | + Map<String, String> paramMap = urlParamToMap(param.getParams()); | |
| 226 | + String sign = paramMap.get("sign"); | |
| 227 | + if (sign == null) { | |
| 228 | + logger.info("推流鉴权失败: 缺少必要参数:sign=md5(user表的pushKey)"); | |
| 229 | + return new HookResultForOnPublish(401, "Unauthorized"); | |
| 230 | + } | |
| 231 | + // 推流自定义播放鉴权码 | |
| 232 | + String callId = paramMap.get("callId"); | |
| 233 | + // 鉴权配置 | |
| 234 | + boolean hasAuthority = userService.checkPushAuthority(callId, sign); | |
| 235 | + if (!hasAuthority) { | |
| 236 | + logger.info("推流鉴权失败: sign 无权限: callId={}. sign={}", callId, sign); | |
| 237 | + return new HookResultForOnPublish(401, "Unauthorized"); | |
| 238 | + } | |
| 239 | + StreamAuthorityInfo streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(param); | |
| 240 | + streamAuthorityInfo.setCallId(callId); | |
| 241 | + streamAuthorityInfo.setSign(sign); | |
| 242 | + // 鉴权通过 | |
| 243 | + redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), param.getStream(), streamAuthorityInfo); | |
| 244 | + } | |
| 245 | + } else { | |
| 246 | + zlmMediaListManager.sendStreamEvent(param.getApp(), param.getStream(), param.getMediaServerId()); | |
| 247 | + } | |
| 248 | + | |
| 249 | + | |
| 250 | + HookResultForOnPublish result = HookResultForOnPublish.SUCCESS(); | |
| 251 | + result.setEnable_audio(true); | |
| 252 | + taskExecutor.execute(() -> { | |
| 253 | + ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_publish, json); | |
| 254 | + if (subscribe != null) { | |
| 255 | + if (mediaInfo != null) { | |
| 256 | + subscribe.response(mediaInfo, param); | |
| 257 | + } else { | |
| 258 | + new HookResultForOnPublish(1, "zlm not register"); | |
| 259 | + } | |
| 260 | + } | |
| 261 | + }); | |
| 262 | + | |
| 263 | + // 是否录像 | |
| 264 | + if ("rtp".equals(param.getApp())) { | |
| 265 | + result.setEnable_mp4(userSetting.getRecordSip()); | |
| 266 | + } else { | |
| 267 | + result.setEnable_mp4(userSetting.isRecordPushLive()); | |
| 268 | + } | |
| 269 | + // 国标流 | |
| 270 | + if ("rtp".equals(param.getApp())) { | |
| 271 | + | |
| 272 | + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, param.getStream()); | |
| 273 | + | |
| 274 | + // 单端口模式下修改流 ID | |
| 275 | + if (!mediaInfo.isRtpEnable() && inviteInfo == null) { | |
| 276 | + String ssrc = String.format("%010d", Long.parseLong(param.getStream(), 16)); | |
| 277 | + inviteInfo = inviteStreamService.getInviteInfoBySSRC(ssrc); | |
| 278 | + if (inviteInfo != null) { | |
| 279 | + result.setStream_replace(inviteInfo.getStream()); | |
| 280 | + logger.info("[ZLM HOOK]推流鉴权 stream: {} 替换为 {}", param.getStream(), inviteInfo.getStream()); | |
| 281 | + } | |
| 282 | + } | |
| 283 | + | |
| 284 | + // 设置音频信息及录制信息 | |
| 285 | + List<SsrcTransaction> ssrcTransactionForAll = sessionManager.getSsrcTransactionForAll(null, null, null, param.getStream()); | |
| 286 | + if (ssrcTransactionForAll != null && ssrcTransactionForAll.size() == 1) { | |
| 287 | + | |
| 288 | + // 为录制国标模拟一个鉴权信息, 方便后续写入录像文件时使用 | |
| 289 | + StreamAuthorityInfo streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(param); | |
| 290 | + streamAuthorityInfo.setApp(param.getApp()); | |
| 291 | + streamAuthorityInfo.setStream(ssrcTransactionForAll.get(0).getStream()); | |
| 292 | + streamAuthorityInfo.setCallId(ssrcTransactionForAll.get(0).getSipTransactionInfo().getCallId()); | |
| 293 | + | |
| 294 | + redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), ssrcTransactionForAll.get(0).getStream(), streamAuthorityInfo); | |
| 295 | + | |
| 296 | + String deviceId = ssrcTransactionForAll.get(0).getDeviceId(); | |
| 297 | + String channelId = ssrcTransactionForAll.get(0).getChannelId(); | |
| 298 | + DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); | |
| 299 | + if (deviceChannel != null) { | |
| 300 | + result.setEnable_audio(deviceChannel.isHasAudio()); | |
| 301 | + } | |
| 302 | + // 如果是录像下载就设置视频间隔十秒 | |
| 303 | + if (ssrcTransactionForAll.get(0).getType() == InviteSessionType.DOWNLOAD) { | |
| 304 | + // 获取录像的总时长,然后设置为这个视频的时长 | |
| 305 | + InviteInfo inviteInfoForDownload = inviteStreamService.getInviteInfo(InviteSessionType.DOWNLOAD, deviceId, channelId, param.getStream()); | |
| 306 | + if (inviteInfoForDownload != null && inviteInfoForDownload.getStreamInfo() != null) { | |
| 307 | + String startTime = inviteInfoForDownload.getStreamInfo().getStartTime(); | |
| 308 | + String endTime = inviteInfoForDownload.getStreamInfo().getEndTime(); | |
| 309 | + long difference = DateUtil.getDifference(startTime, endTime) / 1000; | |
| 310 | + result.setMp4_max_second((int) difference); | |
| 311 | + result.setEnable_mp4(true); | |
| 312 | + // 设置为2保证得到的mp4的时长是正常的 | |
| 313 | + result.setModify_stamp(2); | |
| 314 | + } | |
| 315 | + } | |
| 316 | + // 如果是talk对讲,则默认获取声音 | |
| 317 | + if (ssrcTransactionForAll.get(0).getType() == InviteSessionType.TALK) { | |
| 318 | + result.setEnable_audio(true); | |
| 319 | + } | |
| 320 | + } | |
| 321 | + } else if (param.getApp().equals("broadcast")) { | |
| 322 | + result.setEnable_audio(true); | |
| 323 | + } else if (param.getApp().equals("talk")) { | |
| 324 | + result.setEnable_audio(true); | |
| 325 | + } | |
| 326 | + if (param.getApp().equalsIgnoreCase("rtp")) { | |
| 327 | + String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_" + param.getStream(); | |
| 328 | + OtherRtpSendInfo otherRtpSendInfo = (OtherRtpSendInfo) redisTemplate.opsForValue().get(receiveKey); | |
| 329 | + | |
| 330 | + String receiveKeyForPS = VideoManagerConstants.WVP_OTHER_RECEIVE_PS_INFO + userSetting.getServerId() + "_" + param.getStream(); | |
| 331 | + OtherPsSendInfo otherPsSendInfo = (OtherPsSendInfo) redisTemplate.opsForValue().get(receiveKeyForPS); | |
| 332 | + if (otherRtpSendInfo != null || otherPsSendInfo != null) { | |
| 333 | + result.setEnable_mp4(true); | |
| 334 | + } | |
| 335 | + } | |
| 336 | + logger.info("[ZLM HOOK]推流鉴权 响应:{}->{}->>>>{}", param.getMediaServerId(), param, result); | |
| 337 | + return result; | |
| 338 | + } | |
| 339 | + | |
| 340 | + | |
| 341 | + /** | |
| 342 | + * rtsp/rtmp流注册或注销时触发此事件;此事件对回复不敏感。 | |
| 343 | + */ | |
| 344 | + @ResponseBody | |
| 345 | + @PostMapping(value = "/on_stream_changed", produces = "application/json;charset=UTF-8") | |
| 346 | + public HookResult onStreamChanged(@RequestBody OnStreamChangedHookParam param) { | |
| 347 | + | |
| 348 | + if (param.isRegist()) { | |
| 349 | + logger.info("[ZLM HOOK] 流注册, {}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); | |
| 350 | + } else { | |
| 351 | + logger.info("[ZLM HOOK] 流注销, {}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); | |
| 352 | + } | |
| 353 | + | |
| 354 | + JSONObject json = (JSONObject) JSON.toJSON(param); | |
| 355 | + taskExecutor.execute(() -> { | |
| 356 | + ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_stream_changed, json); | |
| 357 | + MediaServerItem mediaInfo = mediaServerService.getOne(param.getMediaServerId()); | |
| 358 | + if (mediaInfo == null) { | |
| 359 | + logger.info("[ZLM HOOK] 流变化未找到ZLM, {}", param.getMediaServerId()); | |
| 360 | + return; | |
| 361 | + } | |
| 362 | + if (subscribe != null) { | |
| 363 | + subscribe.response(mediaInfo, param); | |
| 364 | + } | |
| 365 | + | |
| 366 | + List<OnStreamChangedHookParam.MediaTrack> tracks = param.getTracks(); | |
| 367 | + // TODO 重构此处逻辑 | |
| 368 | + if (param.isRegist()) { | |
| 369 | + // 处理流注册的鉴权信息, 流注销这里不再删除鉴权信息,下次来了新的鉴权信息会对就的进行覆盖 | |
| 370 | + if (param.getOriginType() == OriginType.RTMP_PUSH.ordinal() | |
| 371 | + || param.getOriginType() == OriginType.RTSP_PUSH.ordinal() | |
| 372 | + || param.getOriginType() == OriginType.RTC_PUSH.ordinal()) { | |
| 373 | + StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream()); | |
| 374 | + if (streamAuthorityInfo == null) { | |
| 375 | + streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(param); | |
| 376 | + } else { | |
| 377 | + streamAuthorityInfo.setOriginType(param.getOriginType()); | |
| 378 | + streamAuthorityInfo.setOriginTypeStr(param.getOriginTypeStr()); | |
| 379 | + } | |
| 380 | + redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), param.getStream(), streamAuthorityInfo); | |
| 381 | + } | |
| 382 | + } | |
| 383 | + if ("rtsp".equals(param.getSchema())) { | |
| 384 | + logger.info("流变化:注册->{}, app->{}, stream->{}", param.isRegist(), param.getApp(), param.getStream()); | |
| 385 | + if (param.isRegist()) { | |
| 386 | + mediaServerService.addCount(param.getMediaServerId()); | |
| 387 | + } else { | |
| 388 | + mediaServerService.removeCount(param.getMediaServerId()); | |
| 389 | + } | |
| 390 | + | |
| 391 | + int updateStatusResult = streamProxyService.updateStatus(param.isRegist(), param.getApp(), param.getStream()); | |
| 392 | + if (updateStatusResult > 0) { | |
| 393 | + | |
| 394 | + } | |
| 395 | + | |
| 396 | + if ("rtp".equals(param.getApp()) && !param.isRegist()) { | |
| 397 | + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, param.getStream()); | |
| 398 | + if (inviteInfo != null && (inviteInfo.getType() == InviteSessionType.PLAY || inviteInfo.getType() == InviteSessionType.PLAYBACK)) { | |
| 399 | + inviteStreamService.removeInviteInfo(inviteInfo); | |
| 400 | + storager.stopPlay(inviteInfo.getDeviceId(), inviteInfo.getChannelId()); | |
| 401 | + } | |
| 402 | + } else if ("broadcast".equals(param.getApp())) { | |
| 403 | + // 语音对讲推流 stream需要满足格式deviceId_channelId | |
| 404 | + if (param.getStream().indexOf("_") > 0) { | |
| 405 | + String[] streamArray = param.getStream().split("_"); | |
| 406 | + if (streamArray.length == 2) { | |
| 407 | + String deviceId = streamArray[0]; | |
| 408 | + String channelId = streamArray[1]; | |
| 409 | + Device device = deviceService.getDevice(deviceId); | |
| 410 | + if (device != null) { | |
| 411 | + if (param.isRegist()) { | |
| 412 | + if (audioBroadcastManager.exit(deviceId, channelId)) { | |
| 413 | + playService.stopAudioBroadcast(deviceId, channelId); | |
| 414 | + } | |
| 415 | + // 开启语音对讲通道 | |
| 416 | + try { | |
| 417 | + playService.audioBroadcastCmd(device, channelId, mediaInfo, param.getApp(), param.getStream(), 60, false, (msg) -> { | |
| 418 | + logger.info("[语音对讲] 通道建立成功, device: {}, channel: {}", deviceId, channelId); | |
| 419 | + }); | |
| 420 | + } catch (InvalidArgumentException | ParseException | SipException e) { | |
| 421 | + logger.error("[命令发送失败] 语音对讲: {}", e.getMessage()); | |
| 422 | + } | |
| 423 | + } else { | |
| 424 | + // 流注销 | |
| 425 | + playService.stopAudioBroadcast(deviceId, channelId); | |
| 426 | + } | |
| 427 | + } else { | |
| 428 | + logger.info("[语音对讲] 未找到设备:{}", deviceId); | |
| 429 | + } | |
| 430 | + } | |
| 431 | + } | |
| 432 | + } else if ("talk".equals(param.getApp())) { | |
| 433 | + // 语音对讲推流 stream需要满足格式deviceId_channelId | |
| 434 | + if (param.getStream().indexOf("_") > 0) { | |
| 435 | + String[] streamArray = param.getStream().split("_"); | |
| 436 | + if (streamArray.length == 2) { | |
| 437 | + String deviceId = streamArray[0]; | |
| 438 | + String channelId = streamArray[1]; | |
| 439 | + Device device = deviceService.getDevice(deviceId); | |
| 440 | + if (device != null) { | |
| 441 | + if (param.isRegist()) { | |
| 442 | + if (audioBroadcastManager.exit(deviceId, channelId)) { | |
| 443 | + playService.stopAudioBroadcast(deviceId, channelId); | |
| 444 | + } | |
| 445 | + // 开启语音对讲通道 | |
| 446 | + playService.talkCmd(device, channelId, mediaInfo, param.getStream(), (msg) -> { | |
| 447 | + logger.info("[语音对讲] 通道建立成功, device: {}, channel: {}", deviceId, channelId); | |
| 448 | + }); | |
| 449 | + } else { | |
| 450 | + // 流注销 | |
| 451 | + playService.stopTalk(device, channelId, param.isRegist()); | |
| 452 | + } | |
| 453 | + } else { | |
| 454 | + logger.info("[语音对讲] 未找到设备:{}", deviceId); | |
| 455 | + } | |
| 456 | + } | |
| 457 | + } | |
| 458 | + | |
| 459 | + } else { | |
| 460 | + if (!"rtp".equals(param.getApp())) { | |
| 461 | + String type = OriginType.values()[param.getOriginType()].getType(); | |
| 462 | + if (param.isRegist()) { | |
| 463 | + StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo( | |
| 464 | + param.getApp(), param.getStream()); | |
| 465 | + String callId = null; | |
| 466 | + if (streamAuthorityInfo != null) { | |
| 467 | + callId = streamAuthorityInfo.getCallId(); | |
| 468 | + } | |
| 469 | + StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaInfo, | |
| 470 | + param.getApp(), param.getStream(), tracks, callId); | |
| 471 | + param.setStreamInfo(new StreamContent(streamInfoByAppAndStream)); | |
| 472 | + redisCatchStorage.addStream(mediaInfo, type, param.getApp(), param.getStream(), param); | |
| 473 | + if (param.getOriginType() == OriginType.RTSP_PUSH.ordinal() | |
| 474 | + || param.getOriginType() == OriginType.RTMP_PUSH.ordinal() | |
| 475 | + || param.getOriginType() == OriginType.RTC_PUSH.ordinal()) { | |
| 476 | + param.setSeverId(userSetting.getServerId()); | |
| 477 | + zlmMediaListManager.addPush(param); | |
| 478 | + | |
| 479 | + // 冗余数据,自己系统中自用 | |
| 480 | + redisCatchStorage.addPushListItem(param.getApp(), param.getStream(), param); | |
| 481 | + } | |
| 482 | + } else { | |
| 483 | + // 兼容流注销时类型从redis记录获取 | |
| 484 | + OnStreamChangedHookParam onStreamChangedHookParam = redisCatchStorage.getStreamInfo( | |
| 485 | + param.getApp(), param.getStream(), param.getMediaServerId()); | |
| 486 | + if (onStreamChangedHookParam != null) { | |
| 487 | + type = OriginType.values()[onStreamChangedHookParam.getOriginType()].getType(); | |
| 488 | + redisCatchStorage.removeStream(mediaInfo.getId(), type, param.getApp(), param.getStream()); | |
| 489 | + if ("PUSH".equalsIgnoreCase(type)) { | |
| 490 | + // 冗余数据,自己系统中自用 | |
| 491 | + redisCatchStorage.removePushListItem(param.getApp(), param.getStream(), param.getMediaServerId()); | |
| 492 | + } | |
| 493 | + } | |
| 494 | + GbStream gbStream = storager.getGbStream(param.getApp(), param.getStream()); | |
| 495 | + if (gbStream != null) { | |
| 496 | +// eventPublisher.catalogEventPublishForStream(null, gbStream, CatalogEvent.OFF); | |
| 497 | + } | |
| 498 | + zlmMediaListManager.removeMedia(param.getApp(), param.getStream()); | |
| 499 | + } | |
| 500 | + GbStream gbStream = storager.getGbStream(param.getApp(), param.getStream()); | |
| 501 | + if (gbStream != null) { | |
| 502 | + if (userSetting.isUsePushingAsStatus()) { | |
| 503 | + eventPublisher.catalogEventPublishForStream(null, gbStream, param.isRegist() ? CatalogEvent.ON : CatalogEvent.OFF); | |
| 504 | + } | |
| 505 | + } | |
| 506 | + if (type != null) { | |
| 507 | + // 发送流变化redis消息 | |
| 508 | + JSONObject jsonObject = new JSONObject(); | |
| 509 | + jsonObject.put("serverId", userSetting.getServerId()); | |
| 510 | + jsonObject.put("app", param.getApp()); | |
| 511 | + jsonObject.put("stream", param.getStream()); | |
| 512 | + jsonObject.put("register", param.isRegist()); | |
| 513 | + jsonObject.put("mediaServerId", param.getMediaServerId()); | |
| 514 | + redisCatchStorage.sendStreamChangeMsg(type, jsonObject); | |
| 515 | + } | |
| 516 | + } | |
| 517 | + } | |
| 518 | + if (!param.isRegist()) { | |
| 519 | + List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByStream(param.getStream()); | |
| 520 | + if (!sendRtpItems.isEmpty()) { | |
| 521 | + for (SendRtpItem sendRtpItem : sendRtpItems) { | |
| 522 | + if (sendRtpItem != null && sendRtpItem.getApp().equals(param.getApp())) { | |
| 523 | + String platformId = sendRtpItem.getPlatformId(); | |
| 524 | + ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId); | |
| 525 | + Device device = deviceService.getDevice(platformId); | |
| 526 | + | |
| 527 | + try { | |
| 528 | + if (platform != null) { | |
| 529 | + commanderFroPlatform.streamByeCmd(platform, sendRtpItem); | |
| 530 | + redisCatchStorage.deleteSendRTPServer(platformId, sendRtpItem.getChannelId(), | |
| 531 | + sendRtpItem.getCallId(), sendRtpItem.getStream()); | |
| 532 | + } else { | |
| 533 | + cmder.streamByeCmd(device, sendRtpItem.getChannelId(), param.getStream(), sendRtpItem.getCallId()); | |
| 534 | + if (sendRtpItem.getPlayType().equals(InviteStreamType.BROADCAST) | |
| 535 | + || sendRtpItem.getPlayType().equals(InviteStreamType.TALK)) { | |
| 536 | + AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); | |
| 537 | + if (audioBroadcastCatch != null) { | |
| 538 | + // 来自上级平台的停止对讲 | |
| 539 | + logger.info("[停止对讲] 来自上级,平台:{}, 通道:{}", sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); | |
| 540 | + audioBroadcastManager.del(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); | |
| 541 | + } | |
| 542 | + } | |
| 543 | + } | |
| 544 | + } catch (SipException | InvalidArgumentException | ParseException | | |
| 545 | + SsrcTransactionNotFoundException e) { | |
| 546 | + logger.error("[命令发送失败] 发送BYE: {}", e.getMessage()); | |
| 547 | + } | |
| 548 | + } | |
| 549 | + } | |
| 550 | + } | |
| 551 | + } | |
| 552 | + } | |
| 553 | + }); | |
| 554 | + return HookResult.SUCCESS(); | |
| 555 | + } | |
| 556 | + | |
| 557 | + /** | |
| 558 | + * 流无人观看时事件,用户可以通过此事件选择是否关闭无人看的流。 | |
| 559 | + */ | |
| 560 | + @ResponseBody | |
| 561 | + @PostMapping(value = "/on_stream_none_reader", produces = "application/json;charset=UTF-8") | |
| 562 | + public JSONObject onStreamNoneReader(@RequestBody OnStreamNoneReaderHookParam param) { | |
| 563 | + | |
| 564 | + logger.info("[ZLM HOOK]流无人观看:{}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), | |
| 565 | + param.getApp(), param.getStream()); | |
| 566 | + JSONObject ret = new JSONObject(); | |
| 567 | + ret.put("code", 0); | |
| 568 | + // 国标类型的流 | |
| 569 | + if ("rtp".equals(param.getApp())) { | |
| 570 | + ret.put("close", userSetting.getStreamOnDemand()); | |
| 571 | + // 国标流, 点播/录像回放/录像下载 | |
| 572 | + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, param.getStream()); | |
| 573 | + // 点播 | |
| 574 | + if (inviteInfo != null) { | |
| 575 | + // 录像下载 | |
| 576 | + if (inviteInfo.getType() == InviteSessionType.DOWNLOAD) { | |
| 577 | + ret.put("close", false); | |
| 578 | + return ret; | |
| 579 | + } | |
| 580 | + // 收到无人观看说明流也没有在往上级推送 | |
| 581 | + if (redisCatchStorage.isChannelSendingRTP(inviteInfo.getChannelId())) { | |
| 582 | + List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByChnnelId( | |
| 583 | + inviteInfo.getChannelId()); | |
| 584 | + if (sendRtpItems.size() > 0) { | |
| 585 | + for (SendRtpItem sendRtpItem : sendRtpItems) { | |
| 586 | + ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId()); | |
| 587 | + try { | |
| 588 | + commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId()); | |
| 589 | + } catch (SipException | InvalidArgumentException | ParseException e) { | |
| 590 | + logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage()); | |
| 591 | + } | |
| 592 | + redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(), | |
| 593 | + sendRtpItem.getCallId(), sendRtpItem.getStream()); | |
| 594 | + if (InviteStreamType.PUSH == sendRtpItem.getPlayType()) { | |
| 595 | + MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, | |
| 596 | + sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getChannelId(), | |
| 597 | + sendRtpItem.getPlatformId(), parentPlatform.getName(), userSetting.getServerId(), sendRtpItem.getMediaServerId()); | |
| 598 | + messageForPushChannel.setPlatFormIndex(parentPlatform.getId()); | |
| 599 | + redisCatchStorage.sendPlatformStopPlayMsg(messageForPushChannel); | |
| 600 | + } | |
| 601 | + } | |
| 602 | + } | |
| 603 | + } | |
| 604 | + Device device = deviceService.getDevice(inviteInfo.getDeviceId()); | |
| 605 | + if (device != null) { | |
| 606 | + try { | |
| 607 | + // 多查询一次防止已经被处理了 | |
| 608 | + InviteInfo info = inviteStreamService.getInviteInfo(inviteInfo.getType(), | |
| 609 | + inviteInfo.getDeviceId(), inviteInfo.getChannelId(), inviteInfo.getStream()); | |
| 610 | + if (info != null) { | |
| 611 | + cmder.streamByeCmd(device, inviteInfo.getChannelId(), | |
| 612 | + inviteInfo.getStream(), null); | |
| 613 | + } else { | |
| 614 | + logger.info("[无人观看] 未找到设备的点播信息: {}, 流:{}", inviteInfo.getDeviceId(), param.getStream()); | |
| 615 | + } | |
| 616 | + } catch (InvalidArgumentException | ParseException | SipException | | |
| 617 | + SsrcTransactionNotFoundException e) { | |
| 618 | + logger.error("[无人观看]点播, 发送BYE失败 {}", e.getMessage()); | |
| 619 | + } | |
| 620 | + } else { | |
| 621 | + logger.info("[无人观看] 未找到设备: {},流:{}", inviteInfo.getDeviceId(), param.getStream()); | |
| 622 | + } | |
| 623 | + | |
| 624 | + inviteStreamService.removeInviteInfo(inviteInfo.getType(), inviteInfo.getDeviceId(), | |
| 625 | + inviteInfo.getChannelId(), inviteInfo.getStream()); | |
| 626 | + storager.stopPlay(inviteInfo.getDeviceId(), inviteInfo.getChannelId()); | |
| 627 | + return ret; | |
| 628 | + } | |
| 629 | + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, param.getStream(), null); | |
| 630 | + if (sendRtpItem != null && "talk".equals(sendRtpItem.getApp())) { | |
| 631 | + ret.put("close", false); | |
| 632 | + return ret; | |
| 633 | + } | |
| 634 | + } else if ("talk".equals(param.getApp()) || "broadcast".equals(param.getApp())) { | |
| 635 | + ret.put("close", false); | |
| 636 | + } else { | |
| 637 | + // 非国标流 推流/拉流代理 | |
| 638 | + // 拉流代理 | |
| 639 | + StreamProxyItem streamProxyItem = streamProxyService.getStreamProxyByAppAndStream(param.getApp(), param.getStream()); | |
| 640 | + if (streamProxyItem != null) { | |
| 641 | + if (streamProxyItem.isEnableRemoveNoneReader()) { | |
| 642 | + // 无人观看自动移除 | |
| 643 | + ret.put("close", true); | |
| 644 | + streamProxyService.del(param.getApp(), param.getStream()); | |
| 645 | + String url = streamProxyItem.getUrl() != null ? streamProxyItem.getUrl() : streamProxyItem.getSrcUrl(); | |
| 646 | + logger.info("[{}/{}]<-[{}] 拉流代理无人观看已经移除", param.getApp(), param.getStream(), url); | |
| 647 | + } else if (streamProxyItem.isEnableDisableNoneReader()) { | |
| 648 | + // 无人观看停用 | |
| 649 | + ret.put("close", true); | |
| 650 | + // 修改数据 | |
| 651 | + streamProxyService.stop(param.getApp(), param.getStream()); | |
| 652 | + } else { | |
| 653 | + // 无人观看不做处理 | |
| 654 | + ret.put("close", false); | |
| 655 | + } | |
| 656 | + return ret; | |
| 657 | + } | |
| 658 | + // TODO 推流具有主动性,暂时不做处理 | |
| 659 | +// StreamPushItem streamPushItem = streamPushService.getPush(app, streamId); | |
| 660 | +// if (streamPushItem != null) { | |
| 661 | +// // TODO 发送停止 | |
| 662 | +// | |
| 663 | +// } | |
| 664 | + } | |
| 665 | + return ret; | |
| 666 | + } | |
| 667 | + | |
| 668 | + /** | |
| 669 | + * 流未找到事件,用户可以在此事件触发时,立即去拉流,这样可以实现按需拉流;此事件对回复不敏感。 | |
| 670 | + */ | |
| 671 | + @ResponseBody | |
| 672 | + @PostMapping(value = "/on_stream_not_found", produces = "application/json;charset=UTF-8") | |
| 673 | + public DeferredResult<HookResult> onStreamNotFound(@RequestBody OnStreamNotFoundHookParam param) { | |
| 674 | + logger.info("[ZLM HOOK] 流未找到:{}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); | |
| 675 | + | |
| 676 | + DeferredResult<HookResult> defaultResult = new DeferredResult<>(); | |
| 677 | + | |
| 678 | + MediaServerItem mediaInfo = mediaServerService.getOne(param.getMediaServerId()); | |
| 679 | + if (!userSetting.isAutoApplyPlay() || mediaInfo == null) { | |
| 680 | + defaultResult.setResult(new HookResult(ErrorCode.ERROR404.getCode(), ErrorCode.ERROR404.getMsg())); | |
| 681 | + return defaultResult; | |
| 682 | + } | |
| 683 | + | |
| 684 | + if ("rtp".equals(param.getApp())) { | |
| 685 | + String[] s = param.getStream().split("_"); | |
| 686 | + if ((s.length != 2 && s.length != 4)) { | |
| 687 | + defaultResult.setResult(HookResult.SUCCESS()); | |
| 688 | + return defaultResult; | |
| 689 | + } | |
| 690 | + String deviceId = s[0]; | |
| 691 | + String channelId = s[1]; | |
| 692 | + Device device = redisCatchStorage.getDevice(deviceId); | |
| 693 | + if (device == null || !device.isOnLine()) { | |
| 694 | + defaultResult.setResult(new HookResult(ErrorCode.ERROR404.getCode(), ErrorCode.ERROR404.getMsg())); | |
| 695 | + return defaultResult; | |
| 696 | + } | |
| 697 | + DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); | |
| 698 | + if (deviceChannel == null) { | |
| 699 | + defaultResult.setResult(new HookResult(ErrorCode.ERROR404.getCode(), ErrorCode.ERROR404.getMsg())); | |
| 700 | + return defaultResult; | |
| 701 | + } | |
| 702 | + if (s.length == 2) { | |
| 703 | + logger.info("[ZLM HOOK] 预览流未找到, 发起自动点播:{}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); | |
| 704 | + | |
| 705 | + RequestMessage msg = new RequestMessage(); | |
| 706 | + String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId; | |
| 707 | + boolean exist = resultHolder.exist(key, null); | |
| 708 | + msg.setKey(key); | |
| 709 | + String uuid = UUID.randomUUID().toString(); | |
| 710 | + msg.setId(uuid); | |
| 711 | + DeferredResult<HookResult> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue()); | |
| 712 | + | |
| 713 | + result.onTimeout(() -> { | |
| 714 | + logger.info("[ZLM HOOK] 预览流自动点播, 等待超时"); | |
| 715 | + msg.setData(new HookResult(ErrorCode.ERROR100.getCode(), "点播超时")); | |
| 716 | + resultHolder.invokeAllResult(msg); | |
| 717 | + inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); | |
| 718 | + storager.stopPlay(deviceId, channelId); | |
| 719 | + }); | |
| 720 | + | |
| 721 | + resultHolder.put(key, uuid, result); | |
| 722 | + | |
| 723 | + if (!exist) { | |
| 724 | + playService.play(mediaInfo, deviceId, channelId, null, (code, message, data) -> { | |
| 725 | + msg.setData(new HookResult(code, message)); | |
| 726 | + resultHolder.invokeResult(msg); | |
| 727 | + }); | |
| 728 | + } | |
| 729 | + return result; | |
| 730 | + } else if (s.length == 4) { | |
| 731 | + // 此时为录像回放, 录像回放格式为> 设备ID_通道ID_开始时间_结束时间 | |
| 732 | + String startTimeStr = s[2]; | |
| 733 | + String endTimeStr = s[3]; | |
| 734 | + if (startTimeStr == null || endTimeStr == null || startTimeStr.length() != 14 || endTimeStr.length() != 14) { | |
| 735 | + defaultResult.setResult(HookResult.SUCCESS()); | |
| 736 | + return defaultResult; | |
| 737 | + } | |
| 738 | + String startTime = DateUtil.urlToyyyy_MM_dd_HH_mm_ss(startTimeStr); | |
| 739 | + String endTime = DateUtil.urlToyyyy_MM_dd_HH_mm_ss(endTimeStr); | |
| 740 | + logger.info("[ZLM HOOK] 回放流未找到, 发起自动点播:{}->{}->{}/{}-{}-{}", | |
| 741 | + param.getMediaServerId(), param.getSchema(), | |
| 742 | + param.getApp(), param.getStream(), | |
| 743 | + startTime, endTime | |
| 744 | + ); | |
| 745 | + RequestMessage msg = new RequestMessage(); | |
| 746 | + String key = DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId; | |
| 747 | + boolean exist = resultHolder.exist(key, null); | |
| 748 | + msg.setKey(key); | |
| 749 | + String uuid = UUID.randomUUID().toString(); | |
| 750 | + msg.setId(uuid); | |
| 751 | + DeferredResult<HookResult> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue()); | |
| 752 | + | |
| 753 | + result.onTimeout(() -> { | |
| 754 | + logger.info("[ZLM HOOK] 回放流自动点播, 等待超时"); | |
| 755 | + // 释放rtpserver | |
| 756 | + msg.setData(new HookResult(ErrorCode.ERROR100.getCode(), "点播超时")); | |
| 757 | + resultHolder.invokeResult(msg); | |
| 758 | + }); | |
| 759 | + | |
| 760 | + resultHolder.put(key, uuid, result); | |
| 761 | + | |
| 762 | + if (!exist) { | |
| 763 | + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaInfo, param.getStream(), null, | |
| 764 | + device.isSsrcCheck(), true, 0, false, false, device.getStreamModeForParam()); | |
| 765 | + playService.playBack(mediaInfo, ssrcInfo, deviceId, channelId, startTime, endTime, (code, message, data) -> { | |
| 766 | + msg.setData(new HookResult(code, message)); | |
| 767 | + resultHolder.invokeResult(msg); | |
| 768 | + }); | |
| 769 | + } | |
| 770 | + return result; | |
| 771 | + } else { | |
| 772 | + defaultResult.setResult(HookResult.SUCCESS()); | |
| 773 | + return defaultResult; | |
| 774 | + } | |
| 775 | + | |
| 776 | + } else { | |
| 777 | + // 拉流代理 | |
| 778 | + StreamProxyItem streamProxyByAppAndStream = streamProxyService.getStreamProxyByAppAndStream(param.getApp(), param.getStream()); | |
| 779 | + if (streamProxyByAppAndStream != null && streamProxyByAppAndStream.isEnableDisableNoneReader()) { | |
| 780 | + streamProxyService.start(param.getApp(), param.getStream()); | |
| 781 | + } | |
| 782 | + DeferredResult<HookResult> result = new DeferredResult<>(); | |
| 783 | + result.setResult(HookResult.SUCCESS()); | |
| 784 | + return result; | |
| 785 | + } | |
| 786 | + } | |
| 787 | + | |
| 788 | + /** | |
| 789 | + * 服务器启动事件,可以用于监听服务器崩溃重启;此事件对回复不敏感。 | |
| 790 | + */ | |
| 791 | + @ResponseBody | |
| 792 | + @PostMapping(value = "/on_server_started", produces = "application/json;charset=UTF-8") | |
| 793 | + public HookResult onServerStarted(HttpServletRequest request, @RequestBody JSONObject jsonObject) { | |
| 794 | + | |
| 795 | + jsonObject.put("ip", request.getRemoteAddr()); | |
| 796 | + ZLMServerConfig zlmServerConfig = JSON.to(ZLMServerConfig.class, jsonObject); | |
| 797 | + zlmServerConfig.setIp(request.getRemoteAddr()); | |
| 798 | + logger.info("[ZLM HOOK] zlm 启动 " + zlmServerConfig.getGeneralMediaServerId()); | |
| 799 | + taskExecutor.execute(() -> { | |
| 800 | + List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_started); | |
| 801 | + if (subscribes != null && subscribes.size() > 0) { | |
| 802 | + for (ZlmHttpHookSubscribe.Event subscribe : subscribes) { | |
| 803 | + subscribe.response(null, zlmServerConfig); | |
| 804 | + } | |
| 805 | + } | |
| 806 | + mediaServerService.zlmServerOnline(zlmServerConfig); | |
| 807 | + }); | |
| 808 | + | |
| 809 | + return HookResult.SUCCESS(); | |
| 810 | + } | |
| 811 | + | |
| 812 | + /** | |
| 813 | + * 发送rtp(startSendRtp)被动关闭时回调 | |
| 814 | + */ | |
| 815 | + @ResponseBody | |
| 816 | + @PostMapping(value = "/on_send_rtp_stopped", produces = "application/json;charset=UTF-8") | |
| 817 | + public HookResult onSendRtpStopped(HttpServletRequest request, @RequestBody OnSendRtpStoppedHookParam param) { | |
| 818 | + | |
| 819 | + logger.info("[ZLM HOOK] rtp发送关闭:{}->{}/{}", param.getMediaServerId(), param.getApp(), param.getStream()); | |
| 820 | + | |
| 821 | + // 查找对应的上级推流,发送停止 | |
| 822 | + if (!"rtp".equals(param.getApp())) { | |
| 823 | + return HookResult.SUCCESS(); | |
| 824 | + } | |
| 825 | + taskExecutor.execute(() -> { | |
| 826 | + List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByStream(param.getStream()); | |
| 827 | + if (sendRtpItems.size() > 0) { | |
| 828 | + for (SendRtpItem sendRtpItem : sendRtpItems) { | |
| 829 | + ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId()); | |
| 830 | + ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrc()); | |
| 831 | + try { | |
| 832 | + commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId()); | |
| 833 | + } catch (SipException | InvalidArgumentException | ParseException e) { | |
| 834 | + logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage()); | |
| 835 | + } | |
| 836 | + redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(), | |
| 837 | + sendRtpItem.getCallId(), sendRtpItem.getStream()); | |
| 838 | + } | |
| 839 | + } | |
| 840 | + }); | |
| 841 | + | |
| 842 | + return HookResult.SUCCESS(); | |
| 843 | + } | |
| 844 | + | |
| 845 | + /** | |
| 846 | + * rtpServer收流超时 | |
| 847 | + */ | |
| 848 | + @ResponseBody | |
| 849 | + @PostMapping(value = "/on_rtp_server_timeout", produces = "application/json;charset=UTF-8") | |
| 850 | + public HookResult onRtpServerTimeout(HttpServletRequest request, @RequestBody OnRtpServerTimeoutHookParam | |
| 851 | + param) { | |
| 852 | + logger.info("[ZLM HOOK] rtpServer收流超时:{}->{}({})", param.getMediaServerId(), param.getStream_id(), param.getSsrc()); | |
| 853 | + | |
| 854 | + taskExecutor.execute(() -> { | |
| 855 | + JSONObject json = (JSONObject) JSON.toJSON(param); | |
| 856 | + List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_rtp_server_timeout); | |
| 857 | + if (subscribes != null && !subscribes.isEmpty()) { | |
| 858 | + for (ZlmHttpHookSubscribe.Event subscribe : subscribes) { | |
| 859 | + subscribe.response(null, param); | |
| 860 | + } | |
| 861 | + } | |
| 862 | + }); | |
| 863 | + | |
| 864 | + return HookResult.SUCCESS(); | |
| 865 | + } | |
| 866 | + | |
| 867 | + /** | |
| 868 | + * 录像完成事件 | |
| 869 | + */ | |
| 870 | + @ResponseBody | |
| 871 | + @PostMapping(value = "/on_record_mp4", produces = "application/json;charset=UTF-8") | |
| 872 | + public HookResult onRecordMp4(HttpServletRequest request, @RequestBody OnRecordMp4HookParam param) { | |
| 873 | + logger.info("[ZLM HOOK] 录像完成事件:{}->{}", param.getMediaServerId(), param.getFile_path()); | |
| 874 | + | |
| 875 | + taskExecutor.execute(() -> { | |
| 876 | + List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_record_mp4); | |
| 877 | + if (subscribes != null && !subscribes.isEmpty()) { | |
| 878 | + for (ZlmHttpHookSubscribe.Event subscribe : subscribes) { | |
| 879 | + subscribe.response(null, param); | |
| 880 | + } | |
| 881 | + } | |
| 882 | + cloudRecordService.addRecord(param); | |
| 883 | + | |
| 884 | + }); | |
| 885 | + | |
| 886 | + return HookResult.SUCCESS(); | |
| 887 | + } | |
| 888 | + | |
| 889 | + private Map<String, String> urlParamToMap(String params) { | |
| 890 | + HashMap<String, String> map = new HashMap<>(); | |
| 891 | + if (ObjectUtils.isEmpty(params)) { | |
| 892 | + return map; | |
| 893 | + } | |
| 894 | + String[] paramsArray = params.split("&"); | |
| 895 | + if (paramsArray.length == 0) { | |
| 896 | + return map; | |
| 897 | + } | |
| 898 | + for (String param : paramsArray) { | |
| 899 | + String[] paramArray = param.split("="); | |
| 900 | + if (paramArray.length == 2) { | |
| 901 | + map.put(paramArray[0], paramArray[1]); | |
| 902 | + } | |
| 903 | + } | |
| 904 | + return map; | |
| 905 | + } | |
| 906 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java
| ... | ... | @@ -96,6 +96,7 @@ public class ZLMRESTfulUtils { |
| 96 | 96 | if (callback == null) { |
| 97 | 97 | try { |
| 98 | 98 | Response response = client.newCall(request).execute(); |
| 99 | + | |
| 99 | 100 | if (response.isSuccessful()) { |
| 100 | 101 | ResponseBody responseBody = response.body(); |
| 101 | 102 | if (responseBody != null) { |
| ... | ... | @@ -103,6 +104,8 @@ public class ZLMRESTfulUtils { |
| 103 | 104 | responseJSON = JSON.parseObject(responseStr); |
| 104 | 105 | } |
| 105 | 106 | }else { |
| 107 | + System.out.println( 2222); | |
| 108 | + System.out.println( response.code()); | |
| 106 | 109 | response.close(); |
| 107 | 110 | Objects.requireNonNull(response.body()).close(); |
| 108 | 111 | } |
| ... | ... | @@ -111,11 +114,11 @@ public class ZLMRESTfulUtils { |
| 111 | 114 | |
| 112 | 115 | if(e instanceof SocketTimeoutException){ |
| 113 | 116 | //读取超时超时异常 |
| 114 | - logger.error(String.format("读取ZLM数据失败: %s, %s", url, e.getMessage())); | |
| 117 | + logger.error(String.format("读取ZLM数据超时失败: %s, %s", url, e.getMessage())); | |
| 115 | 118 | } |
| 116 | 119 | if(e instanceof ConnectException){ |
| 117 | 120 | //判断连接异常,我这里是报Failed to connect to 10.7.5.144 |
| 118 | - logger.error(String.format("连接ZLM失败: %s, %s", url, e.getMessage())); | |
| 121 | + logger.error(String.format("连接ZLM连接失败: %s, %s", url, e.getMessage())); | |
| 119 | 122 | } |
| 120 | 123 | |
| 121 | 124 | }catch (Exception e){ |
| ... | ... | @@ -323,6 +326,10 @@ public class ZLMRESTfulUtils { |
| 323 | 326 | return sendPost(mediaServerItem, "startSendRtpPassive",param, null); |
| 324 | 327 | } |
| 325 | 328 | |
| 329 | + public JSONObject startSendRtpPassive(MediaServerItem mediaServerItem, Map<String, Object> param, RequestCallback callback) { | |
| 330 | + return sendPost(mediaServerItem, "startSendRtpPassive",param, callback); | |
| 331 | + } | |
| 332 | + | |
| 326 | 333 | public JSONObject stopSendRtp(MediaServerItem mediaServerItem, Map<String, Object> param) { |
| 327 | 334 | return sendPost(mediaServerItem, "stopSendRtp",param, null); |
| 328 | 335 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerFactory.java
| ... | ... | @@ -42,7 +42,7 @@ public class ZLMServerFactory { |
| 42 | 42 | * @param tcpMode 0/null udp 模式,1 tcp 被动模式, 2 tcp 主动模式。 |
| 43 | 43 | * @return |
| 44 | 44 | */ |
| 45 | - public int createRTPServer(MediaServerItem mediaServerItem, String streamId, long ssrc, Integer port, Boolean reUsePort, Integer tcpMode) { | |
| 45 | + public int createRTPServer(MediaServerItem mediaServerItem, String streamId, long ssrc, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode) { | |
| 46 | 46 | int result = -1; |
| 47 | 47 | // 查询此rtp server 是否已经存在 |
| 48 | 48 | JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaServerItem, streamId); |
| ... | ... | @@ -58,7 +58,7 @@ public class ZLMServerFactory { |
| 58 | 58 | JSONObject jsonObject = zlmresTfulUtils.closeRtpServer(mediaServerItem, param); |
| 59 | 59 | if (jsonObject != null ) { |
| 60 | 60 | if (jsonObject.getInteger("code") == 0) { |
| 61 | - return createRTPServer(mediaServerItem, streamId, ssrc, port, reUsePort, tcpMode); | |
| 61 | + return createRTPServer(mediaServerItem, streamId, ssrc, port,onlyAuto, reUsePort, tcpMode); | |
| 62 | 62 | }else { |
| 63 | 63 | logger.warn("[开启rtpServer], 重启RtpServer错误"); |
| 64 | 64 | } |
| ... | ... | @@ -86,6 +86,9 @@ public class ZLMServerFactory { |
| 86 | 86 | }else { |
| 87 | 87 | param.put("port", port); |
| 88 | 88 | } |
| 89 | + if (onlyAuto != null) { | |
| 90 | + param.put("only_audio", onlyAuto?"1":"0"); | |
| 91 | + } | |
| 89 | 92 | if (ssrc != 0) { |
| 90 | 93 | param.put("ssrc", ssrc); |
| 91 | 94 | } |
| ... | ... | @@ -111,9 +114,10 @@ public class ZLMServerFactory { |
| 111 | 114 | Map<String, Object> param = new HashMap<>(); |
| 112 | 115 | param.put("stream_id", streamId); |
| 113 | 116 | JSONObject jsonObject = zlmresTfulUtils.closeRtpServer(serverItem, param); |
| 117 | + logger.info("关闭RTP Server " + jsonObject); | |
| 114 | 118 | if (jsonObject != null ) { |
| 115 | 119 | if (jsonObject.getInteger("code") == 0) { |
| 116 | - result = jsonObject.getInteger("hit") == 1; | |
| 120 | + result = jsonObject.getInteger("hit") >= 1; | |
| 117 | 121 | }else { |
| 118 | 122 | logger.error("关闭RTP Server 失败: " + jsonObject.getString("msg")); |
| 119 | 123 | } |
| ... | ... | @@ -206,7 +210,7 @@ public class ZLMServerFactory { |
| 206 | 210 | sendRtpItem.setPort(port); |
| 207 | 211 | sendRtpItem.setSsrc(ssrc); |
| 208 | 212 | sendRtpItem.setApp(app); |
| 209 | - sendRtpItem.setStreamId(stream); | |
| 213 | + sendRtpItem.setStream(stream); | |
| 210 | 214 | sendRtpItem.setPlatformId(platformId); |
| 211 | 215 | sendRtpItem.setChannelId(channelId); |
| 212 | 216 | sendRtpItem.setTcp(tcp); |
| ... | ... | @@ -227,10 +231,14 @@ public class ZLMServerFactory { |
| 227 | 231 | /** |
| 228 | 232 | * 调用zlm RESTFUL API —— startSendRtpPassive |
| 229 | 233 | */ |
| 230 | - public JSONObject startSendRtpStreamForPassive(MediaServerItem mediaServerItem, Map<String, Object>param) { | |
| 234 | + public JSONObject startSendRtpPassive(MediaServerItem mediaServerItem, Map<String, Object>param) { | |
| 231 | 235 | return zlmresTfulUtils.startSendRtpPassive(mediaServerItem, param); |
| 232 | 236 | } |
| 233 | 237 | |
| 238 | + public JSONObject startSendRtpPassive(MediaServerItem mediaServerItem, Map<String, Object>param, ZLMRESTfulUtils.RequestCallback callback) { | |
| 239 | + return zlmresTfulUtils.startSendRtpPassive(mediaServerItem, param, callback); | |
| 240 | + } | |
| 241 | + | |
| 234 | 242 | /** |
| 235 | 243 | * 查询待转推的流是否就绪 |
| 236 | 244 | */ |
| ... | ... | @@ -266,11 +274,11 @@ public class ZLMServerFactory { |
| 266 | 274 | return 0; |
| 267 | 275 | } |
| 268 | 276 | Integer code = mediaInfo.getInteger("code"); |
| 269 | - if ( code < 0) { | |
| 277 | + if (code < 0) { | |
| 270 | 278 | logger.warn("查询流({}/{})是否有其它观看者时得到: {}", app, streamId, mediaInfo.getString("msg")); |
| 271 | 279 | return -1; |
| 272 | 280 | } |
| 273 | - if ( code == 0 && mediaInfo.getBoolean("online") != null && !mediaInfo.getBoolean("online")) { | |
| 281 | + if ( code == 0 && mediaInfo.getBoolean("online") != null && ! mediaInfo.getBoolean("online")) { | |
| 274 | 282 | logger.warn("查询流({}/{})是否有其它观看者时得到: {}", app, streamId, mediaInfo.getString("msg")); |
| 275 | 283 | return -1; |
| 276 | 284 | } |
| ... | ... | @@ -289,13 +297,54 @@ public class ZLMServerFactory { |
| 289 | 297 | result= true; |
| 290 | 298 | logger.info("[停止RTP推流] 成功"); |
| 291 | 299 | } else { |
| 292 | - logger.error("[停止RTP推流] 失败: {}, 参数:{}->\r\n{}",jsonObject.getString("msg"), JSON.toJSON(param), jsonObject); | |
| 300 | + logger.warn("[停止RTP推流] 失败: {}, 参数:{}->\r\n{}",jsonObject.getString("msg"), JSON.toJSON(param), jsonObject); | |
| 293 | 301 | } |
| 294 | 302 | return result; |
| 295 | 303 | } |
| 296 | 304 | |
| 297 | - public void closeAllSendRtpStream() { | |
| 305 | + public JSONObject startSendRtp(MediaServerItem mediaInfo, SendRtpItem sendRtpItem) { | |
| 306 | + String is_Udp = sendRtpItem.isTcp() ? "0" : "1"; | |
| 307 | + logger.info("rtp/{}开始推流, 目标={}:{},SSRC={}", sendRtpItem.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc()); | |
| 308 | + Map<String, Object> param = new HashMap<>(12); | |
| 309 | + param.put("vhost","__defaultVhost__"); | |
| 310 | + param.put("app",sendRtpItem.getApp()); | |
| 311 | + param.put("stream",sendRtpItem.getStream()); | |
| 312 | + param.put("ssrc", sendRtpItem.getSsrc()); | |
| 313 | + param.put("src_port", sendRtpItem.getLocalPort()); | |
| 314 | + param.put("pt", sendRtpItem.getPt()); | |
| 315 | + param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0"); | |
| 316 | + param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0"); | |
| 317 | + if (!sendRtpItem.isTcp()) { | |
| 318 | + // udp模式下开启rtcp保活 | |
| 319 | + param.put("udp_rtcp_timeout", sendRtpItem.isRtcp()? "1":"0"); | |
| 320 | + } | |
| 298 | 321 | |
| 322 | + if (mediaInfo == null) { | |
| 323 | + return null; | |
| 324 | + } | |
| 325 | + // 如果是非严格模式,需要关闭端口占用 | |
| 326 | + JSONObject startSendRtpStreamResult = null; | |
| 327 | + if (sendRtpItem.getLocalPort() != 0) { | |
| 328 | + if (sendRtpItem.isTcpActive()) { | |
| 329 | + startSendRtpStreamResult = startSendRtpPassive(mediaInfo, param); | |
| 330 | + System.out.println(JSON.toJSON(param)); | |
| 331 | + }else { | |
| 332 | + param.put("is_udp", is_Udp); | |
| 333 | + param.put("dst_url", sendRtpItem.getIp()); | |
| 334 | + param.put("dst_port", sendRtpItem.getPort()); | |
| 335 | + startSendRtpStreamResult = startSendRtpStream(mediaInfo, param); | |
| 336 | + } | |
| 337 | + }else { | |
| 338 | + if (sendRtpItem.isTcpActive()) { | |
| 339 | + startSendRtpStreamResult = startSendRtpPassive(mediaInfo, param); | |
| 340 | + }else { | |
| 341 | + param.put("is_udp", is_Udp); | |
| 342 | + param.put("dst_url", sendRtpItem.getIp()); | |
| 343 | + param.put("dst_port", sendRtpItem.getPort()); | |
| 344 | + startSendRtpStreamResult = startSendRtpStream(mediaInfo, param); | |
| 345 | + } | |
| 346 | + } | |
| 347 | + return startSendRtpStreamResult; | |
| 299 | 348 | } |
| 300 | 349 | |
| 301 | 350 | public Boolean updateRtpServerSSRC(MediaServerItem mediaServerItem, String streamId, String ssrc) { | ... | ... |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZlmHttpHookSubscribe.java
| ... | ... | @@ -39,6 +39,7 @@ public class ZlmHttpHookSubscribe { |
| 39 | 39 | hookSubscribe.setExpires(expiresInstant); |
| 40 | 40 | } |
| 41 | 41 | allSubscribes.computeIfAbsent(hookSubscribe.getHookType(), k -> new ConcurrentHashMap<>()).put(hookSubscribe, event); |
| 42 | + System.out.println(allSubscribes); | |
| 42 | 43 | } |
| 43 | 44 | |
| 44 | 45 | public ZlmHttpHookSubscribe.Event sendNotify(HookType type, JSONObject hookResponse) { |
| ... | ... | @@ -49,6 +50,7 @@ public class ZlmHttpHookSubscribe { |
| 49 | 50 | } |
| 50 | 51 | for (IHookSubscribe key : eventMap.keySet()) { |
| 51 | 52 | Boolean result = null; |
| 53 | + | |
| 52 | 54 | for (String s : key.getContent().keySet()) { |
| 53 | 55 | if (result == null) { |
| 54 | 56 | result = key.getContent().getString(s).equals(hookResponse.getString(s)); | ... | ... |
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeFactory.java
| ... | ... | @@ -35,6 +35,21 @@ public class HookSubscribeFactory { |
| 35 | 35 | return hookSubscribe; |
| 36 | 36 | } |
| 37 | 37 | |
| 38 | + public static HookSubscribeForStreamPush on_publish(String app, String stream, String scheam, String mediaServerId) { | |
| 39 | + HookSubscribeForStreamPush hookSubscribe = new HookSubscribeForStreamPush(); | |
| 40 | + JSONObject subscribeKey = new JSONObject(); | |
| 41 | + subscribeKey.put("app", app); | |
| 42 | + subscribeKey.put("stream", stream); | |
| 43 | + if (scheam != null) { | |
| 44 | + subscribeKey.put("schema", scheam); | |
| 45 | + } | |
| 46 | + subscribeKey.put("mediaServerId", mediaServerId); | |
| 47 | + hookSubscribe.setContent(subscribeKey); | |
| 48 | + | |
| 49 | + return hookSubscribe; | |
| 50 | + } | |
| 51 | + | |
| 52 | + | |
| 38 | 53 | public static HookSubscribeForServerStarted on_server_started() { |
| 39 | 54 | HookSubscribeForServerStarted hookSubscribe = new HookSubscribeForServerStarted(); |
| 40 | 55 | hookSubscribe.setContent(new JSONObject()); |
| ... | ... | @@ -52,4 +67,5 @@ public class HookSubscribeFactory { |
| 52 | 67 | |
| 53 | 68 | return hookSubscribe; |
| 54 | 69 | } |
| 70 | + | |
| 55 | 71 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForStreamPush.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.media.zlm.dto; | |
| 2 | + | |
| 3 | + | |
| 4 | +import com.alibaba.fastjson2.JSONObject; | |
| 5 | + | |
| 6 | +import java.time.Instant; | |
| 7 | + | |
| 8 | +/** | |
| 9 | + * hook订阅-开始推流 | |
| 10 | + * @author lin | |
| 11 | + */ | |
| 12 | +public class HookSubscribeForStreamPush implements IHookSubscribe{ | |
| 13 | + | |
| 14 | + private HookType hookType = HookType.on_publish; | |
| 15 | + | |
| 16 | + private JSONObject content; | |
| 17 | + | |
| 18 | + private Instant expires; | |
| 19 | + | |
| 20 | + @Override | |
| 21 | + public HookType getHookType() { | |
| 22 | + return hookType; | |
| 23 | + } | |
| 24 | + | |
| 25 | + @Override | |
| 26 | + public JSONObject getContent() { | |
| 27 | + return content; | |
| 28 | + } | |
| 29 | + | |
| 30 | + public void setContent(JSONObject content) { | |
| 31 | + this.content = content; | |
| 32 | + } | |
| 33 | + | |
| 34 | + @Override | |
| 35 | + public Instant getExpires() { | |
| 36 | + return expires; | |
| 37 | + } | |
| 38 | + | |
| 39 | + @Override | |
| 40 | + public void setExpires(Instant expires) { | |
| 41 | + this.expires = expires; | |
| 42 | + } | |
| 43 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItemLite.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.media.zlm.dto; | |
| 2 | + | |
| 3 | + | |
| 4 | +/** | |
| 5 | + * 精简的MediaServerItem信息,方便给前端返回数据 | |
| 6 | + */ | |
| 7 | +public class MediaServerItemLite { | |
| 8 | + | |
| 9 | + private String id; | |
| 10 | + | |
| 11 | + private String ip; | |
| 12 | + | |
| 13 | + private String hookIp; | |
| 14 | + | |
| 15 | + private String sdpIp; | |
| 16 | + | |
| 17 | + private String streamIp; | |
| 18 | + | |
| 19 | + private int httpPort; | |
| 20 | + | |
| 21 | + private int httpSSlPort; | |
| 22 | + | |
| 23 | + private int rtmpPort; | |
| 24 | + | |
| 25 | + private int rtmpSSlPort; | |
| 26 | + | |
| 27 | + private int rtpProxyPort; | |
| 28 | + | |
| 29 | + private int rtspPort; | |
| 30 | + | |
| 31 | + private int rtspSSLPort; | |
| 32 | + | |
| 33 | + private String secret; | |
| 34 | + | |
| 35 | + private int recordAssistPort; | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + public MediaServerItemLite(MediaServerItem mediaServerItem) { | |
| 40 | + this.id = mediaServerItem.getId(); | |
| 41 | + this.ip = mediaServerItem.getIp(); | |
| 42 | + this.hookIp = mediaServerItem.getHookIp(); | |
| 43 | + this.sdpIp = mediaServerItem.getSdpIp(); | |
| 44 | + this.streamIp = mediaServerItem.getStreamIp(); | |
| 45 | + this.httpPort = mediaServerItem.getHttpPort(); | |
| 46 | + this.httpSSlPort = mediaServerItem.getHttpSSlPort(); | |
| 47 | + this.rtmpPort = mediaServerItem.getRtmpPort(); | |
| 48 | + this.rtmpSSlPort = mediaServerItem.getRtmpSSlPort(); | |
| 49 | + this.rtpProxyPort = mediaServerItem.getRtpProxyPort(); | |
| 50 | + this.rtspPort = mediaServerItem.getRtspPort(); | |
| 51 | + this.rtspSSLPort = mediaServerItem.getRtspSSLPort(); | |
| 52 | + this.secret = mediaServerItem.getSecret(); | |
| 53 | + this.recordAssistPort = mediaServerItem.getRecordAssistPort(); | |
| 54 | + } | |
| 55 | + | |
| 56 | + public String getId() { | |
| 57 | + return id; | |
| 58 | + } | |
| 59 | + | |
| 60 | + public void setId(String id) { | |
| 61 | + this.id = id; | |
| 62 | + } | |
| 63 | + | |
| 64 | + public String getIp() { | |
| 65 | + return ip; | |
| 66 | + } | |
| 67 | + | |
| 68 | + public void setIp(String ip) { | |
| 69 | + this.ip = ip; | |
| 70 | + } | |
| 71 | + | |
| 72 | + public String getHookIp() { | |
| 73 | + return hookIp; | |
| 74 | + } | |
| 75 | + | |
| 76 | + public void setHookIp(String hookIp) { | |
| 77 | + this.hookIp = hookIp; | |
| 78 | + } | |
| 79 | + | |
| 80 | + public String getSdpIp() { | |
| 81 | + return sdpIp; | |
| 82 | + } | |
| 83 | + | |
| 84 | + public void setSdpIp(String sdpIp) { | |
| 85 | + this.sdpIp = sdpIp; | |
| 86 | + } | |
| 87 | + | |
| 88 | + public String getStreamIp() { | |
| 89 | + return streamIp; | |
| 90 | + } | |
| 91 | + | |
| 92 | + public void setStreamIp(String streamIp) { | |
| 93 | + this.streamIp = streamIp; | |
| 94 | + } | |
| 95 | + | |
| 96 | + public int getHttpPort() { | |
| 97 | + return httpPort; | |
| 98 | + } | |
| 99 | + | |
| 100 | + public void setHttpPort(int httpPort) { | |
| 101 | + this.httpPort = httpPort; | |
| 102 | + } | |
| 103 | + | |
| 104 | + public int getHttpSSlPort() { | |
| 105 | + return httpSSlPort; | |
| 106 | + } | |
| 107 | + | |
| 108 | + public void setHttpSSlPort(int httpSSlPort) { | |
| 109 | + this.httpSSlPort = httpSSlPort; | |
| 110 | + } | |
| 111 | + | |
| 112 | + public int getRtmpPort() { | |
| 113 | + return rtmpPort; | |
| 114 | + } | |
| 115 | + | |
| 116 | + public void setRtmpPort(int rtmpPort) { | |
| 117 | + this.rtmpPort = rtmpPort; | |
| 118 | + } | |
| 119 | + | |
| 120 | + public int getRtmpSSlPort() { | |
| 121 | + return rtmpSSlPort; | |
| 122 | + } | |
| 123 | + | |
| 124 | + public void setRtmpSSlPort(int rtmpSSlPort) { | |
| 125 | + this.rtmpSSlPort = rtmpSSlPort; | |
| 126 | + } | |
| 127 | + | |
| 128 | + public int getRtpProxyPort() { | |
| 129 | + return rtpProxyPort; | |
| 130 | + } | |
| 131 | + | |
| 132 | + public void setRtpProxyPort(int rtpProxyPort) { | |
| 133 | + this.rtpProxyPort = rtpProxyPort; | |
| 134 | + } | |
| 135 | + | |
| 136 | + public int getRtspPort() { | |
| 137 | + return rtspPort; | |
| 138 | + } | |
| 139 | + | |
| 140 | + public void setRtspPort(int rtspPort) { | |
| 141 | + this.rtspPort = rtspPort; | |
| 142 | + } | |
| 143 | + | |
| 144 | + public int getRtspSSLPort() { | |
| 145 | + return rtspSSLPort; | |
| 146 | + } | |
| 147 | + | |
| 148 | + public void setRtspSSLPort(int rtspSSLPort) { | |
| 149 | + this.rtspSSLPort = rtspSSLPort; | |
| 150 | + } | |
| 151 | + | |
| 152 | + | |
| 153 | + public String getSecret() { | |
| 154 | + return secret; | |
| 155 | + } | |
| 156 | + | |
| 157 | + public void setSecret(String secret) { | |
| 158 | + this.secret = secret; | |
| 159 | + } | |
| 160 | + | |
| 161 | + public int getRecordAssistPort() { | |
| 162 | + return recordAssistPort; | |
| 163 | + } | |
| 164 | + | |
| 165 | + public void setRecordAssistPort(int recordAssistPort) { | |
| 166 | + this.recordAssistPort = recordAssistPort; | |
| 167 | + } | |
| 168 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java
| ... | ... | @@ -45,8 +45,10 @@ public interface IMediaServerService { |
| 45 | 45 | |
| 46 | 46 | void updateVmServer(List<MediaServerItem> mediaServerItemList); |
| 47 | 47 | |
| 48 | - SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, | |
| 49 | - boolean isPlayback, Integer port, Boolean reUsePort, Integer tcpMode); | |
| 48 | + SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String presetSsrc, boolean ssrcCheck, | |
| 49 | + boolean isPlayback, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode); | |
| 50 | + | |
| 51 | + SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback, Integer port, Boolean onlyAuto); | |
| 50 | 52 | |
| 51 | 53 | void closeRTPServer(MediaServerItem mediaServerItem, String streamId); |
| 52 | 54 | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/IMediaService.java
| ... | ... | @@ -40,5 +40,5 @@ public interface IMediaService { |
| 40 | 40 | * @param stream |
| 41 | 41 | * @return |
| 42 | 42 | */ |
| 43 | - StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String addr, String callId); | |
| 43 | + StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String addr, String callId, boolean isPlay); | |
| 44 | 44 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/IPlatformService.java
| 1 | 1 | package com.genersoft.iot.vmp.service; |
| 2 | 2 | |
| 3 | +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; | |
| 3 | 4 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| 5 | +import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | |
| 6 | +import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; | |
| 7 | +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | |
| 8 | +import com.genersoft.iot.vmp.service.bean.InviteTimeOutCallback; | |
| 4 | 9 | import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo; |
| 5 | 10 | import com.github.pagehelper.PageInfo; |
| 6 | 11 | |
| 12 | +import javax.sip.InvalidArgumentException; | |
| 13 | +import javax.sip.SipException; | |
| 14 | +import java.text.ParseException; | |
| 15 | + | |
| 7 | 16 | /** |
| 8 | 17 | * 国标平台的业务类 |
| 9 | 18 | * @author lin |
| ... | ... | @@ -56,5 +65,21 @@ public interface IPlatformService { |
| 56 | 65 | */ |
| 57 | 66 | void sendNotifyMobilePosition(String platformId); |
| 58 | 67 | |
| 68 | + /** | |
| 69 | + * 向上级发送语音喊话的消息 | |
| 70 | + * @param platform 平台 | |
| 71 | + * @param channelId 通道 | |
| 72 | + * @param hookEvent hook事件 | |
| 73 | + * @param errorEvent 信令错误事件 | |
| 74 | + * @param timeoutCallback 超时事件 | |
| 75 | + */ | |
| 76 | + void broadcastInvite(ParentPlatform platform, String channelId, MediaServerItem mediaServerItem, ZlmHttpHookSubscribe.Event hookEvent, | |
| 77 | + SipSubscribe.Event errorEvent, InviteTimeOutCallback timeoutCallback) throws InvalidArgumentException, ParseException, SipException; | |
| 78 | + | |
| 79 | + /** | |
| 80 | + * 语音喊话回复BYE | |
| 81 | + */ | |
| 82 | + void stopBroadcast(ParentPlatform platform, DeviceChannel channel, String stream,boolean sendBye, MediaServerItem mediaServerItem); | |
| 83 | + | |
| 59 | 84 | void addSimulatedSubscribeInfo(ParentPlatform parentPlatform); |
| 60 | 85 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
| 1 | 1 | package com.genersoft.iot.vmp.service; |
| 2 | 2 | |
| 3 | +import com.alibaba.fastjson2.JSONObject; | |
| 3 | 4 | import com.genersoft.iot.vmp.common.StreamInfo; |
| 4 | 5 | import com.genersoft.iot.vmp.conf.exception.ServiceException; |
| 5 | 6 | import com.genersoft.iot.vmp.gb28181.bean.Device; |
| 7 | +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; | |
| 8 | +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; | |
| 6 | 9 | import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; |
| 7 | 10 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 11 | +import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam; | |
| 8 | 12 | import com.genersoft.iot.vmp.service.bean.ErrorCallback; |
| 9 | 13 | import com.genersoft.iot.vmp.service.bean.SSRCInfo; |
| 14 | +import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; | |
| 15 | +import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioBroadcastEvent; | |
| 16 | +import gov.nist.javax.sip.message.SIPResponse; | |
| 10 | 17 | |
| 11 | 18 | import javax.sip.InvalidArgumentException; |
| 12 | 19 | import javax.sip.SipException; |
| 20 | +import javax.sip.header.CallIdHeader; | |
| 13 | 21 | import java.text.ParseException; |
| 22 | +import java.util.Map; | |
| 14 | 23 | |
| 15 | 24 | /** |
| 16 | 25 | * 点播处理 |
| ... | ... | @@ -21,6 +30,8 @@ public interface IPlayService { |
| 21 | 30 | ErrorCallback<Object> callback); |
| 22 | 31 | SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback<Object> callback); |
| 23 | 32 | |
| 33 | + StreamInfo onPublishHandlerForPlay(MediaServerItem mediaServerItem, HookParam hookParam, String deviceId, String channelId); | |
| 34 | + | |
| 24 | 35 | MediaServerItem getNewMediaServerItem(Device device); |
| 25 | 36 | |
| 26 | 37 | void playBack(String deviceId, String channelId, String startTime, String endTime, ErrorCallback<Object> callback); |
| ... | ... | @@ -34,10 +45,27 @@ public interface IPlayService { |
| 34 | 45 | |
| 35 | 46 | void zlmServerOnline(String mediaServerId); |
| 36 | 47 | |
| 48 | + AudioBroadcastResult audioBroadcast(Device device, String channelId, Boolean broadcastMode); | |
| 49 | + | |
| 50 | + boolean audioBroadcastCmd(Device device, String channelId, MediaServerItem mediaServerItem, String app, String stream, int timeout, boolean isFromPlatform, AudioBroadcastEvent event) throws InvalidArgumentException, ParseException, SipException; | |
| 51 | + | |
| 52 | + boolean audioBroadcastInUse(Device device, String channelId); | |
| 53 | + | |
| 54 | + void stopAudioBroadcast(String deviceId, String channelId); | |
| 55 | + | |
| 37 | 56 | void pauseRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException; |
| 38 | 57 | |
| 39 | 58 | void resumeRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException; |
| 40 | 59 | |
| 60 | + void startPushStream(SendRtpItem sendRtpItem, SIPResponse sipResponse, ParentPlatform platform, CallIdHeader callIdHeader); | |
| 61 | + | |
| 62 | + void startSendRtpStreamHand(SendRtpItem sendRtpItem, Object correlationInfo, | |
| 63 | + JSONObject jsonObject, Map<String, Object> param, CallIdHeader callIdHeader); | |
| 64 | + | |
| 65 | + void talkCmd(Device device, String channelId, MediaServerItem mediaServerItem, String stream, AudioBroadcastEvent event); | |
| 66 | + | |
| 67 | + void stopTalk(Device device, String channelId, Boolean streamIsReady); | |
| 68 | + | |
| 41 | 69 | void getSnap(String deviceId, String channelId, String fileName, ErrorCallback errorCallback); |
| 42 | 70 | |
| 43 | 71 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/bean/RequestSendItemMsg.java
| ... | ... | @@ -72,7 +72,7 @@ public class RequestSendItemMsg { |
| 72 | 72 | |
| 73 | 73 | |
| 74 | 74 | public static RequestSendItemMsg getInstance(String serverId, String mediaServerId, String app, String stream, String ip, int port, |
| 75 | - String ssrc, String platformId, String channelId, Boolean isTcp, Boolean rtcp, String platformName) { | |
| 75 | + String ssrc, String platformId, String channelId, Boolean isTcp, Boolean rtcp, String platformName) { | |
| 76 | 76 | RequestSendItemMsg requestSendItemMsg = new RequestSendItemMsg(); |
| 77 | 77 | requestSendItemMsg.setServerId(serverId); |
| 78 | 78 | requestSendItemMsg.setMediaServerId(mediaServerId); | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
| ... | ... | @@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants; |
| 6 | 6 | import com.genersoft.iot.vmp.conf.DynamicTask; |
| 7 | 7 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 8 | 8 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 9 | +import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; | |
| 9 | 10 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 10 | 11 | import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; |
| 11 | 12 | import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask; |
| ... | ... | @@ -13,6 +14,8 @@ import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask; |
| 13 | 14 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; |
| 14 | 15 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; |
| 15 | 16 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler; |
| 17 | +import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; | |
| 18 | +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | |
| 16 | 19 | import com.genersoft.iot.vmp.service.IDeviceChannelService; |
| 17 | 20 | import com.genersoft.iot.vmp.service.IDeviceService; |
| 18 | 21 | import com.genersoft.iot.vmp.service.IInviteStreamService; |
| ... | ... | @@ -37,9 +40,7 @@ import javax.sip.InvalidArgumentException; |
| 37 | 40 | import javax.sip.SipException; |
| 38 | 41 | import java.text.ParseException; |
| 39 | 42 | import java.time.Instant; |
| 40 | -import java.util.ArrayList; | |
| 41 | -import java.util.Collections; | |
| 42 | -import java.util.List; | |
| 43 | +import java.util.*; | |
| 43 | 44 | import java.util.concurrent.TimeUnit; |
| 44 | 45 | |
| 45 | 46 | /** |
| ... | ... | @@ -98,6 +99,12 @@ public class DeviceServiceImpl implements IDeviceService { |
| 98 | 99 | @Autowired |
| 99 | 100 | private IMediaServerService mediaServerService; |
| 100 | 101 | |
| 102 | + @Autowired | |
| 103 | + private AudioBroadcastManager audioBroadcastManager; | |
| 104 | + | |
| 105 | + @Autowired | |
| 106 | + private ZLMRESTfulUtils zlmresTfulUtils; | |
| 107 | + | |
| 101 | 108 | @Override |
| 102 | 109 | public void online(Device device, SipTransactionInfo sipTransactionInfo) { |
| 103 | 110 | logger.info("[设备上线] deviceId:{}->{}:{}", device.getDeviceId(), device.getIp(), device.getPort()); |
| ... | ... | @@ -229,6 +236,25 @@ public class DeviceServiceImpl implements IDeviceService { |
| 229 | 236 | // 移除订阅 |
| 230 | 237 | removeCatalogSubscribe(device, null); |
| 231 | 238 | removeMobilePositionSubscribe(device, null); |
| 239 | + | |
| 240 | + List<AudioBroadcastCatch> audioBroadcastCatches = audioBroadcastManager.get(deviceId); | |
| 241 | + if (audioBroadcastCatches.size() > 0) { | |
| 242 | + for (AudioBroadcastCatch audioBroadcastCatch : audioBroadcastCatches) { | |
| 243 | + | |
| 244 | + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(deviceId, audioBroadcastCatch.getChannelId(), null, null); | |
| 245 | + if (sendRtpItem != null) { | |
| 246 | + redisCatchStorage.deleteSendRTPServer(deviceId, sendRtpItem.getChannelId(), null, null); | |
| 247 | + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | |
| 248 | + Map<String, Object> param = new HashMap<>(); | |
| 249 | + param.put("vhost", "__defaultVhost__"); | |
| 250 | + param.put("app", sendRtpItem.getApp()); | |
| 251 | + param.put("stream", sendRtpItem.getStream()); | |
| 252 | + zlmresTfulUtils.stopSendRtp(mediaInfo, param); | |
| 253 | + } | |
| 254 | + | |
| 255 | + audioBroadcastManager.del(deviceId, audioBroadcastCatch.getChannelId()); | |
| 256 | + } | |
| 257 | + } | |
| 232 | 258 | } |
| 233 | 259 | |
| 234 | 260 | @Override |
| ... | ... | @@ -569,7 +595,7 @@ public class DeviceServiceImpl implements IDeviceService { |
| 569 | 595 | deviceInStore.setSsrcCheck(device.isSsrcCheck()); |
| 570 | 596 | //作为消息通道 |
| 571 | 597 | deviceInStore.setAsMessageChannel(device.isAsMessageChannel()); |
| 572 | - | |
| 598 | + | |
| 573 | 599 | deviceMapper.updateCustom(deviceInStore); |
| 574 | 600 | redisCatchStorage.updateDevice(deviceInStore); |
| 575 | 601 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
| ... | ... | @@ -119,6 +119,8 @@ public class MediaServerServiceImpl implements IMediaServerService { |
| 119 | 119 | |
| 120 | 120 | |
| 121 | 121 | |
| 122 | + | |
| 123 | + | |
| 122 | 124 | /** |
| 123 | 125 | * 初始化 |
| 124 | 126 | */ |
| ... | ... | @@ -145,7 +147,7 @@ public class MediaServerServiceImpl implements IMediaServerService { |
| 145 | 147 | |
| 146 | 148 | @Override |
| 147 | 149 | public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String presetSsrc, boolean ssrcCheck, |
| 148 | - boolean isPlayback, Integer port, Boolean reUsePort, Integer tcpMode) { | |
| 150 | + boolean isPlayback, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode) { | |
| 149 | 151 | if (mediaServerItem == null || mediaServerItem.getId() == null) { |
| 150 | 152 | logger.info("[openRTPServer] 失败, mediaServerItem == null || mediaServerItem.getId() == null"); |
| 151 | 153 | return null; |
| ... | ... | @@ -171,7 +173,7 @@ public class MediaServerServiceImpl implements IMediaServerService { |
| 171 | 173 | } |
| 172 | 174 | int rtpServerPort; |
| 173 | 175 | if (mediaServerItem.isRtpEnable()) { |
| 174 | - rtpServerPort = zlmServerFactory.createRTPServer(mediaServerItem, streamId, ssrcCheck ? Long.parseLong(ssrc) : 0, port, reUsePort, tcpMode); | |
| 176 | + rtpServerPort = zlmServerFactory.createRTPServer(mediaServerItem, streamId, ssrcCheck ? Long.parseLong(ssrc) : 0, port, onlyAuto, reUsePort, tcpMode); | |
| 175 | 177 | } else { |
| 176 | 178 | rtpServerPort = mediaServerItem.getRtpProxyPort(); |
| 177 | 179 | } |
| ... | ... | @@ -179,6 +181,12 @@ public class MediaServerServiceImpl implements IMediaServerService { |
| 179 | 181 | } |
| 180 | 182 | |
| 181 | 183 | @Override |
| 184 | + public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback, Integer port, Boolean onlyAuto) { | |
| 185 | + return openRTPServer(mediaServerItem, streamId, ssrc, ssrcCheck, isPlayback, port, onlyAuto, null, 0); | |
| 186 | + } | |
| 187 | + | |
| 188 | + | |
| 189 | + @Override | |
| 182 | 190 | public void closeRTPServer(MediaServerItem mediaServerItem, String streamId) { |
| 183 | 191 | if (mediaServerItem == null) { |
| 184 | 192 | return; |
| ... | ... | @@ -198,7 +206,7 @@ public class MediaServerServiceImpl implements IMediaServerService { |
| 198 | 206 | @Override |
| 199 | 207 | public void closeRTPServer(String mediaServerId, String streamId) { |
| 200 | 208 | MediaServerItem mediaServerItem = this.getOne(mediaServerId); |
| 201 | - if (mediaServerItem.isRtpEnable()) { | |
| 209 | + if (mediaServerItem != null && mediaServerItem.isRtpEnable()) { | |
| 202 | 210 | closeRTPServer(mediaServerItem, streamId); |
| 203 | 211 | } |
| 204 | 212 | zlmresTfulUtils.closeStreams(mediaServerItem, "rtp", streamId); |
| ... | ... | @@ -306,6 +314,7 @@ public class MediaServerServiceImpl implements IMediaServerService { |
| 306 | 314 | return JsonUtil.redisJsonToObject(redisTemplate, key, MediaServerItem.class); |
| 307 | 315 | } |
| 308 | 316 | |
| 317 | + | |
| 309 | 318 | @Override |
| 310 | 319 | public MediaServerItem getDefaultMediaServer() { |
| 311 | 320 | return mediaServerMapper.queryDefault(); | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
| ... | ... | @@ -4,21 +4,18 @@ import com.alibaba.fastjson2.JSON; |
| 4 | 4 | import com.alibaba.fastjson2.JSONArray; |
| 5 | 5 | import com.alibaba.fastjson2.JSONObject; |
| 6 | 6 | import com.genersoft.iot.vmp.common.StreamInfo; |
| 7 | -import com.genersoft.iot.vmp.common.StreamURL; | |
| 8 | 7 | import com.genersoft.iot.vmp.conf.MediaConfig; |
| 9 | 8 | import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; |
| 10 | 9 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 11 | 10 | import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; |
| 12 | 11 | import com.genersoft.iot.vmp.service.IMediaServerService; |
| 12 | +import com.genersoft.iot.vmp.service.IMediaService; | |
| 13 | 13 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 14 | 14 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 15 | -import com.genersoft.iot.vmp.service.IMediaService; | |
| 16 | 15 | import org.springframework.beans.factory.annotation.Autowired; |
| 17 | 16 | import org.springframework.stereotype.Service; |
| 18 | 17 | import org.springframework.util.ObjectUtils; |
| 19 | 18 | |
| 20 | -import java.net.URL; | |
| 21 | - | |
| 22 | 19 | @Service |
| 23 | 20 | public class MediaServiceImpl implements IMediaService { |
| 24 | 21 | |
| ... | ... | @@ -42,7 +39,7 @@ public class MediaServiceImpl implements IMediaService { |
| 42 | 39 | |
| 43 | 40 | @Override |
| 44 | 41 | public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String callId) { |
| 45 | - return getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, null, callId); | |
| 42 | + return getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, null, callId, true); | |
| 46 | 43 | } |
| 47 | 44 | |
| 48 | 45 | @Override |
| ... | ... | @@ -70,9 +67,9 @@ public class MediaServiceImpl implements IMediaService { |
| 70 | 67 | JSONObject mediaJSON = data.getJSONObject(0); |
| 71 | 68 | JSONArray tracks = mediaJSON.getJSONArray("tracks"); |
| 72 | 69 | if (authority) { |
| 73 | - streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, addr, calld); | |
| 70 | + streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, addr, calld, true); | |
| 74 | 71 | }else { |
| 75 | - streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, addr,null); | |
| 72 | + streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, addr,null, true); | |
| 76 | 73 | } |
| 77 | 74 | } |
| 78 | 75 | } |
| ... | ... | @@ -87,7 +84,7 @@ public class MediaServiceImpl implements IMediaService { |
| 87 | 84 | } |
| 88 | 85 | |
| 89 | 86 | @Override |
| 90 | - public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String addr, String callId) { | |
| 87 | + public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String addr, String callId, boolean isPlay) { | |
| 91 | 88 | StreamInfo streamInfoResult = new StreamInfo(); |
| 92 | 89 | streamInfoResult.setStream(stream); |
| 93 | 90 | streamInfoResult.setApp(app); |
| ... | ... | @@ -104,10 +101,9 @@ public class MediaServiceImpl implements IMediaService { |
| 104 | 101 | streamInfoResult.setFmp4(addr, mediaInfo.getHttpPort(),mediaInfo.getHttpSSlPort(), app, stream, callIdParam); |
| 105 | 102 | streamInfoResult.setHls(addr, mediaInfo.getHttpPort(),mediaInfo.getHttpSSlPort(), app, stream, callIdParam); |
| 106 | 103 | streamInfoResult.setTs(addr, mediaInfo.getHttpPort(),mediaInfo.getHttpSSlPort(), app, stream, callIdParam); |
| 107 | - streamInfoResult.setRtc(addr, mediaInfo.getHttpPort(),mediaInfo.getHttpSSlPort(), app, stream, callIdParam); | |
| 104 | + streamInfoResult.setRtc(addr, mediaInfo.getHttpPort(),mediaInfo.getHttpSSlPort(), app, stream, callIdParam, isPlay); | |
| 108 | 105 | |
| 109 | 106 | streamInfoResult.setTracks(tracks); |
| 110 | 107 | return streamInfoResult; |
| 111 | 108 | } |
| 112 | - | |
| 113 | 109 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformChannelServiceImpl.java
| ... | ... | @@ -164,7 +164,7 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService { |
| 164 | 164 | return 0; |
| 165 | 165 | } |
| 166 | 166 | if (ObjectUtils.isEmpty(catalogId)) { |
| 167 | - catalogId = null; | |
| 167 | + catalogId = null; | |
| 168 | 168 | } |
| 169 | 169 | |
| 170 | 170 | List<DeviceChannel> deviceChannels = platformChannelMapper.queryAllChannelInCatalog(platformId, catalogId); | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java
| 1 | 1 | package com.genersoft.iot.vmp.service.impl; |
| 2 | 2 | |
| 3 | +import com.alibaba.fastjson2.JSONObject; | |
| 4 | +import com.genersoft.iot.vmp.common.InviteInfo; | |
| 5 | +import com.genersoft.iot.vmp.common.InviteSessionStatus; | |
| 6 | +import com.genersoft.iot.vmp.common.InviteSessionType; | |
| 3 | 7 | import com.baomidou.dynamic.datasource.annotation.DS; |
| 4 | 8 | import com.genersoft.iot.vmp.conf.DynamicTask; |
| 5 | 9 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 10 | +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; | |
| 6 | 11 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 7 | 12 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| 8 | 13 | import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; |
| 14 | +import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | |
| 9 | 15 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; |
| 16 | +import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; | |
| 17 | +import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; | |
| 18 | +import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; | |
| 19 | +import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; | |
| 20 | +import com.genersoft.iot.vmp.gb28181.utils.SipUtils; | |
| 10 | 21 | import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; |
| 11 | 22 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 23 | +import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; | |
| 24 | +import com.genersoft.iot.vmp.service.IInviteStreamService; | |
| 12 | 25 | import com.genersoft.iot.vmp.service.IMediaServerService; |
| 13 | 26 | import com.genersoft.iot.vmp.service.IPlatformService; |
| 14 | -import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; | |
| 27 | +import com.genersoft.iot.vmp.service.IPlayService; | |
| 28 | +import com.genersoft.iot.vmp.service.bean.*; | |
| 15 | 29 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 16 | 30 | import com.genersoft.iot.vmp.storager.dao.*; |
| 17 | 31 | import com.genersoft.iot.vmp.utils.DateUtil; |
| 18 | 32 | import com.github.pagehelper.PageHelper; |
| 19 | 33 | import com.github.pagehelper.PageInfo; |
| 34 | +import gov.nist.javax.sip.message.SIPRequest; | |
| 35 | +import gov.nist.javax.sip.message.SIPResponse; | |
| 20 | 36 | import org.slf4j.Logger; |
| 21 | 37 | import org.slf4j.LoggerFactory; |
| 22 | 38 | import org.springframework.beans.factory.annotation.Autowired; |
| 23 | 39 | import org.springframework.stereotype.Service; |
| 24 | 40 | |
| 41 | +import javax.sdp.*; | |
| 25 | 42 | import javax.sip.InvalidArgumentException; |
| 43 | +import javax.sip.ResponseEvent; | |
| 44 | +import javax.sip.PeerUnavailableException; | |
| 26 | 45 | import javax.sip.SipException; |
| 27 | 46 | import java.text.ParseException; |
| 28 | 47 | import java.util.HashMap; |
| 29 | 48 | import java.util.List; |
| 30 | 49 | import java.util.Map; |
| 31 | 50 | import java.util.UUID; |
| 51 | +import java.util.HashMap; | |
| 52 | +import java.util.List; | |
| 53 | +import java.util.Map; | |
| 54 | +import java.util.UUID; | |
| 55 | +import java.util.*; | |
| 32 | 56 | |
| 33 | 57 | /** |
| 34 | 58 | * @author lin |
| ... | ... | @@ -48,15 +72,6 @@ public class PlatformServiceImpl implements IPlatformService { |
| 48 | 72 | private ParentPlatformMapper platformMapper; |
| 49 | 73 | |
| 50 | 74 | @Autowired |
| 51 | - private PlatformCatalogMapper catalogMapper; | |
| 52 | - | |
| 53 | - @Autowired | |
| 54 | - private PlatformChannelMapper platformChannelMapper; | |
| 55 | - | |
| 56 | - @Autowired | |
| 57 | - private PlatformGbStreamMapper platformGbStreamMapper; | |
| 58 | - | |
| 59 | - @Autowired | |
| 60 | 75 | private IRedisCatchStorage redisCatchStorage; |
| 61 | 76 | |
| 62 | 77 | @Autowired |
| ... | ... | @@ -83,6 +98,21 @@ public class PlatformServiceImpl implements IPlatformService { |
| 83 | 98 | @Autowired |
| 84 | 99 | private UserSetting userSetting; |
| 85 | 100 | |
| 101 | + @Autowired | |
| 102 | + private ZlmHttpHookSubscribe subscribe; | |
| 103 | + | |
| 104 | + @Autowired | |
| 105 | + private VideoStreamSessionManager streamSession; | |
| 106 | + | |
| 107 | + | |
| 108 | + @Autowired | |
| 109 | + private IPlayService playService; | |
| 110 | + | |
| 111 | + @Autowired | |
| 112 | + private IInviteStreamService inviteStreamService; | |
| 113 | + | |
| 114 | + @Autowired | |
| 115 | + private ZLMRESTfulUtils zlmresTfulUtils; | |
| 86 | 116 | |
| 87 | 117 | |
| 88 | 118 | @Override |
| ... | ... | @@ -374,7 +404,7 @@ public class PlatformServiceImpl implements IPlatformService { |
| 374 | 404 | Map<String, Object> param = new HashMap<>(3); |
| 375 | 405 | param.put("vhost", "__defaultVhost__"); |
| 376 | 406 | param.put("app", sendRtpItem.getApp()); |
| 377 | - param.put("stream", sendRtpItem.getStreamId()); | |
| 407 | + param.put("stream", sendRtpItem.getStream()); | |
| 378 | 408 | zlmServerFactory.stopSendRtpStream(mediaInfo, param); |
| 379 | 409 | } |
| 380 | 410 | } |
| ... | ... | @@ -431,4 +461,319 @@ public class PlatformServiceImpl implements IPlatformService { |
| 431 | 461 | } |
| 432 | 462 | } |
| 433 | 463 | } |
| 464 | + | |
| 465 | + @Override | |
| 466 | + public void broadcastInvite(ParentPlatform platform, String channelId, MediaServerItem mediaServerItem, ZlmHttpHookSubscribe.Event hookEvent, | |
| 467 | + SipSubscribe.Event errorEvent, InviteTimeOutCallback timeoutCallback) throws InvalidArgumentException, ParseException, SipException { | |
| 468 | + | |
| 469 | + if (mediaServerItem == null) { | |
| 470 | + logger.info("[国标级联] 语音喊话未找到可用的zlm. platform: {}", platform.getServerGBId()); | |
| 471 | + return; | |
| 472 | + } | |
| 473 | + InviteInfo inviteInfoForOld = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, platform.getServerGBId(), channelId); | |
| 474 | + | |
| 475 | + if (inviteInfoForOld != null && inviteInfoForOld.getStreamInfo() != null) { | |
| 476 | + // 如果zlm不存在这个流,则删除数据即可 | |
| 477 | + MediaServerItem mediaServerItemForStreamInfo = mediaServerService.getOne(inviteInfoForOld.getStreamInfo().getMediaServerId()); | |
| 478 | + if (mediaServerItemForStreamInfo != null) { | |
| 479 | + Boolean ready = zlmServerFactory.isStreamReady(mediaServerItemForStreamInfo, inviteInfoForOld.getStreamInfo().getApp(), inviteInfoForOld.getStreamInfo().getStream()); | |
| 480 | + if (!ready) { | |
| 481 | + // 错误存在于redis中的数据 | |
| 482 | + inviteStreamService.removeInviteInfo(inviteInfoForOld); | |
| 483 | + }else { | |
| 484 | + // 流确实尚在推流,直接回调结果 | |
| 485 | + OnStreamChangedHookParam hookParam = new OnStreamChangedHookParam(); | |
| 486 | + hookParam.setApp(inviteInfoForOld.getStreamInfo().getApp()); | |
| 487 | + hookParam.setStream(inviteInfoForOld.getStreamInfo().getStream()); | |
| 488 | + | |
| 489 | + hookEvent.response(mediaServerItemForStreamInfo, hookParam); | |
| 490 | + return; | |
| 491 | + } | |
| 492 | + } | |
| 493 | + } | |
| 494 | + | |
| 495 | + String streamId = null; | |
| 496 | + if (mediaServerItem.isRtpEnable()) { | |
| 497 | + streamId = String.format("%s_%s", platform.getServerGBId(), channelId); | |
| 498 | + } | |
| 499 | + // 默认不进行SSRC校验, TODO 后续可改为配置 | |
| 500 | + boolean ssrcCheck = false; | |
| 501 | + int tcpMode; | |
| 502 | + if (userSetting.getBroadcastForPlatform().equalsIgnoreCase("TCP-PASSIVE")) { | |
| 503 | + tcpMode = 1; | |
| 504 | + }else if (userSetting.getBroadcastForPlatform().equalsIgnoreCase("TCP-ACTIVE")) { | |
| 505 | + tcpMode = 2; | |
| 506 | + } else { | |
| 507 | + tcpMode = 0; | |
| 508 | + } | |
| 509 | + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, ssrcCheck, false, null, true, false, tcpMode); | |
| 510 | + if (ssrcInfo == null || ssrcInfo.getPort() < 0) { | |
| 511 | + logger.info("[国标级联] 发起语音喊话 开启端口监听失败, platform: {}, channel: {}", platform.getServerGBId(), channelId); | |
| 512 | + SipSubscribe.EventResult<Object> eventResult = new SipSubscribe.EventResult<>(); | |
| 513 | + eventResult.statusCode = -1; | |
| 514 | + eventResult.msg = "端口监听失败"; | |
| 515 | + eventResult.type = SipSubscribe.EventResultType.failedToGetPort; | |
| 516 | + errorEvent.response(eventResult); | |
| 517 | + return; | |
| 518 | + } | |
| 519 | + logger.info("[国标级联] 语音喊话,发起Invite消息 deviceId: {}, channelId: {},收流端口: {}, 收流模式:{}, SSRC: {}, SSRC校验:{}", | |
| 520 | + platform.getServerGBId(), channelId, ssrcInfo.getPort(), userSetting.getBroadcastForPlatform(), ssrcInfo.getSsrc(), ssrcCheck); | |
| 521 | + | |
| 522 | + // 初始化redis中的invite消息状态 | |
| 523 | + InviteInfo inviteInfo = InviteInfo.getInviteInfo(platform.getServerGBId(), channelId, ssrcInfo.getStream(), ssrcInfo, | |
| 524 | + mediaServerItem.getSdpIp(), ssrcInfo.getPort(), userSetting.getBroadcastForPlatform(), InviteSessionType.BROADCAST, | |
| 525 | + InviteSessionStatus.ready); | |
| 526 | + inviteStreamService.updateInviteInfo(inviteInfo); | |
| 527 | + String timeOutTaskKey = UUID.randomUUID().toString(); | |
| 528 | + dynamicTask.startDelay(timeOutTaskKey, () -> { | |
| 529 | + // 执行超时任务时查询是否已经成功,成功了则不执行超时任务,防止超时任务取消失败的情况 | |
| 530 | + InviteInfo inviteInfoForBroadcast = inviteStreamService.getInviteInfo(InviteSessionType.BROADCAST, platform.getServerGBId(), channelId, null); | |
| 531 | + if (inviteInfoForBroadcast == null) { | |
| 532 | + logger.info("[国标级联] 发起语音喊话 收流超时 deviceId: {}, channelId: {},端口:{}, SSRC: {}", platform.getServerGBId(), channelId, ssrcInfo.getPort(), ssrcInfo.getSsrc()); | |
| 533 | + // 点播超时回复BYE 同时释放ssrc以及此次点播的资源 | |
| 534 | + try { | |
| 535 | + commanderForPlatform.streamByeCmd(platform, channelId, ssrcInfo.getStream(), null, null); | |
| 536 | + } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) { | |
| 537 | + logger.error("[点播超时], 发送BYE失败 {}", e.getMessage()); | |
| 538 | + } finally { | |
| 539 | + timeoutCallback.run(1, "收流超时"); | |
| 540 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | |
| 541 | + mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); | |
| 542 | + streamSession.remove(platform.getServerGBId(), channelId, ssrcInfo.getStream()); | |
| 543 | + mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); | |
| 544 | + } | |
| 545 | + } | |
| 546 | + }, userSetting.getPlayTimeout()); | |
| 547 | + commanderForPlatform.broadcastInviteCmd(platform, channelId, mediaServerItem, ssrcInfo, (mediaServerItemForInvite, hookParam)->{ | |
| 548 | + logger.info("[国标级联] 发起语音喊话 收到上级推流 deviceId: {}, channelId: {}", platform.getServerGBId(), channelId); | |
| 549 | + dynamicTask.stop(timeOutTaskKey); | |
| 550 | + // hook响应 | |
| 551 | + playService.onPublishHandlerForPlay(mediaServerItemForInvite, hookParam, platform.getServerGBId(), channelId); | |
| 552 | + // 收到流 | |
| 553 | + if (hookEvent != null) { | |
| 554 | + hookEvent.response(mediaServerItem, hookParam); | |
| 555 | + } | |
| 556 | + }, event -> { | |
| 557 | + | |
| 558 | + inviteOKHandler(event, ssrcInfo, tcpMode, ssrcCheck, mediaServerItem, platform, channelId, timeOutTaskKey, | |
| 559 | + null, inviteInfo, InviteSessionType.BROADCAST); | |
| 560 | +// // 收到200OK 检测ssrc是否有变化,防止上级自定义了ssrc | |
| 561 | +// ResponseEvent responseEvent = (ResponseEvent) event.event; | |
| 562 | +// String contentString = new String(responseEvent.getResponse().getRawContent()); | |
| 563 | +// // 获取ssrc | |
| 564 | +// int ssrcIndex = contentString.indexOf("y="); | |
| 565 | +// // 检查是否有y字段 | |
| 566 | +// if (ssrcIndex >= 0) { | |
| 567 | +// //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段 TODO 后续对不规范的非10位ssrc兼容 | |
| 568 | +// String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); | |
| 569 | +// // 查询到ssrc不一致且开启了ssrc校验则需要针对处理 | |
| 570 | +// if (ssrcInfo.getSsrc().equals(ssrcInResponse) || ssrcCheck) { | |
| 571 | +// tcpActiveHandler(platform, ) | |
| 572 | +// return; | |
| 573 | +// } | |
| 574 | +// logger.info("[点播消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse); | |
| 575 | +// if (!mediaServerItem.isRtpEnable()) { | |
| 576 | +// logger.info("[点播消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); | |
| 577 | +// // 释放ssrc | |
| 578 | +// mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | |
| 579 | +// // 单端口模式streamId也有变化,需要重新设置监听 | |
| 580 | +// if (!mediaServerItem.isRtpEnable()) { | |
| 581 | +// // 添加订阅 | |
| 582 | +// HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId()); | |
| 583 | +// subscribe.removeSubscribe(hookSubscribe); | |
| 584 | +// hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase()); | |
| 585 | +// subscribe.addSubscribe(hookSubscribe, (mediaServerItemInUse, hookParam) -> { | |
| 586 | +// logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + hookParam); | |
| 587 | +// dynamicTask.stop(timeOutTaskKey); | |
| 588 | +// // hook响应 | |
| 589 | +// playService.onPublishHandlerForPlay(mediaServerItemInUse, hookParam, platform.getServerGBId(), channelId); | |
| 590 | +// hookEvent.response(mediaServerItemInUse, hookParam); | |
| 591 | +// }); | |
| 592 | +// } | |
| 593 | +// // 关闭rtp server | |
| 594 | +// mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); | |
| 595 | +// // 重新开启ssrc server | |
| 596 | +// mediaServerService.openRTPServer(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse, false, false, ssrcInfo.getPort(), true, false, tcpMode); | |
| 597 | +// } | |
| 598 | +// } | |
| 599 | + }, eventResult -> { | |
| 600 | + // 收到错误回复 | |
| 601 | + if (errorEvent != null) { | |
| 602 | + errorEvent.response(eventResult); | |
| 603 | + } | |
| 604 | + }); | |
| 605 | + } | |
| 606 | + | |
| 607 | + private void inviteOKHandler(SipSubscribe.EventResult eventResult, SSRCInfo ssrcInfo, int tcpMode, boolean ssrcCheck, MediaServerItem mediaServerItem, | |
| 608 | + ParentPlatform platform, String channelId, String timeOutTaskKey, ErrorCallback<Object> callback, | |
| 609 | + InviteInfo inviteInfo, InviteSessionType inviteSessionType){ | |
| 610 | + inviteInfo.setStatus(InviteSessionStatus.ok); | |
| 611 | + ResponseEvent responseEvent = (ResponseEvent) eventResult.event; | |
| 612 | + String contentString = new String(responseEvent.getResponse().getRawContent()); | |
| 613 | + System.out.println(1111); | |
| 614 | + System.out.println(contentString); | |
| 615 | + String ssrcInResponse = SipUtils.getSsrcFromSdp(contentString); | |
| 616 | + // 兼容回复的消息中缺少ssrc(y字段)的情况 | |
| 617 | + if (ssrcInResponse == null) { | |
| 618 | + ssrcInResponse = ssrcInfo.getSsrc(); | |
| 619 | + } | |
| 620 | + if (ssrcInfo.getSsrc().equals(ssrcInResponse)) { | |
| 621 | + // ssrc 一致 | |
| 622 | + if (mediaServerItem.isRtpEnable()) { | |
| 623 | + // 多端口 | |
| 624 | + if (tcpMode == 2) { | |
| 625 | + tcpActiveHandler(platform, channelId, contentString, mediaServerItem, tcpMode, ssrcCheck, | |
| 626 | + timeOutTaskKey, ssrcInfo, callback); | |
| 627 | + } | |
| 628 | + }else { | |
| 629 | + // 单端口 | |
| 630 | + if (tcpMode == 2) { | |
| 631 | + logger.warn("[Invite 200OK] 单端口收流模式不支持tcp主动模式收流"); | |
| 632 | + } | |
| 633 | + } | |
| 634 | + }else { | |
| 635 | + logger.info("[Invite 200OK] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse); | |
| 636 | + // ssrc 不一致 | |
| 637 | + if (mediaServerItem.isRtpEnable()) { | |
| 638 | + // 多端口 | |
| 639 | + if (ssrcCheck) { | |
| 640 | + // ssrc检验 | |
| 641 | + // 更新ssrc | |
| 642 | + logger.info("[Invite 200OK] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); | |
| 643 | + // 释放ssrc | |
| 644 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | |
| 645 | + Boolean result = mediaServerService.updateRtpServerSSRC(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse); | |
| 646 | + if (!result) { | |
| 647 | + try { | |
| 648 | + logger.warn("[Invite 200OK] 更新ssrc失败,停止喊话 {}/{}", platform.getServerGBId(), channelId); | |
| 649 | + commanderForPlatform.streamByeCmd(platform, channelId, ssrcInfo.getStream(), null, null); | |
| 650 | + } catch (InvalidArgumentException | SipException | ParseException | SsrcTransactionNotFoundException e) { | |
| 651 | + logger.error("[命令发送失败] 停止播放, 发送BYE: {}", e.getMessage()); | |
| 652 | + } | |
| 653 | + | |
| 654 | + dynamicTask.stop(timeOutTaskKey); | |
| 655 | + // 释放ssrc | |
| 656 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | |
| 657 | + | |
| 658 | + streamSession.remove(platform.getServerGBId(), channelId, ssrcInfo.getStream()); | |
| 659 | + | |
| 660 | + callback.run(InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(), | |
| 661 | + "下级自定义了ssrc,重新设置收流信息失败", null); | |
| 662 | + inviteStreamService.call(inviteSessionType, platform.getServerGBId(), channelId, null, | |
| 663 | + InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(), | |
| 664 | + "下级自定义了ssrc,重新设置收流信息失败", null); | |
| 665 | + | |
| 666 | + }else { | |
| 667 | + ssrcInfo.setSsrc(ssrcInResponse); | |
| 668 | + inviteInfo.setSsrcInfo(ssrcInfo); | |
| 669 | + inviteInfo.setStream(ssrcInfo.getStream()); | |
| 670 | + if (tcpMode == 2) { | |
| 671 | + if (mediaServerItem.isRtpEnable()) { | |
| 672 | + tcpActiveHandler(platform, channelId, contentString, mediaServerItem, tcpMode, ssrcCheck, | |
| 673 | + timeOutTaskKey, ssrcInfo, callback); | |
| 674 | + }else { | |
| 675 | + logger.warn("[Invite 200OK] 单端口收流模式不支持tcp主动模式收流"); | |
| 676 | + } | |
| 677 | + } | |
| 678 | + inviteStreamService.updateInviteInfo(inviteInfo); | |
| 679 | + } | |
| 680 | + }else { | |
| 681 | + ssrcInfo.setSsrc(ssrcInResponse); | |
| 682 | + inviteInfo.setSsrcInfo(ssrcInfo); | |
| 683 | + inviteInfo.setStream(ssrcInfo.getStream()); | |
| 684 | + if (tcpMode == 2) { | |
| 685 | + if (mediaServerItem.isRtpEnable()) { | |
| 686 | + tcpActiveHandler(platform, channelId, contentString, mediaServerItem, tcpMode, ssrcCheck, | |
| 687 | + timeOutTaskKey, ssrcInfo, callback); | |
| 688 | + }else { | |
| 689 | + logger.warn("[Invite 200OK] 单端口收流模式不支持tcp主动模式收流"); | |
| 690 | + } | |
| 691 | + } | |
| 692 | + inviteStreamService.updateInviteInfo(inviteInfo); | |
| 693 | + } | |
| 694 | + }else { | |
| 695 | + if (ssrcInResponse != null) { | |
| 696 | + // 单端口 | |
| 697 | + // 重新订阅流上线 | |
| 698 | + SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(inviteInfo.getDeviceId(), | |
| 699 | + inviteInfo.getChannelId(), null, inviteInfo.getStream()); | |
| 700 | + streamSession.remove(inviteInfo.getDeviceId(), | |
| 701 | + inviteInfo.getChannelId(), inviteInfo.getStream()); | |
| 702 | + inviteStreamService.updateInviteInfoForSSRC(inviteInfo, ssrcInResponse); | |
| 703 | + streamSession.put(platform.getServerGBId(), channelId, ssrcTransaction.getCallId(), | |
| 704 | + inviteInfo.getStream(), ssrcInResponse, mediaServerItem.getId(), (SIPResponse) responseEvent.getResponse(), inviteSessionType); | |
| 705 | + } | |
| 706 | + } | |
| 707 | + } | |
| 708 | + } | |
| 709 | + | |
| 710 | + | |
| 711 | + private void tcpActiveHandler(ParentPlatform platform, String channelId, String contentString, | |
| 712 | + MediaServerItem mediaServerItem, int tcpMode, boolean ssrcCheck, | |
| 713 | + String timeOutTaskKey, SSRCInfo ssrcInfo, ErrorCallback<Object> callback){ | |
| 714 | + if (tcpMode != 2) { | |
| 715 | + return; | |
| 716 | + } | |
| 717 | + | |
| 718 | + String substring; | |
| 719 | + if (contentString.indexOf("y=") > 0) { | |
| 720 | + substring = contentString.substring(0, contentString.indexOf("y=")); | |
| 721 | + }else { | |
| 722 | + substring = contentString; | |
| 723 | + } | |
| 724 | + try { | |
| 725 | + SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring); | |
| 726 | + int port = -1; | |
| 727 | + Vector mediaDescriptions = sdp.getMediaDescriptions(true); | |
| 728 | + for (Object description : mediaDescriptions) { | |
| 729 | + MediaDescription mediaDescription = (MediaDescription) description; | |
| 730 | + Media media = mediaDescription.getMedia(); | |
| 731 | + | |
| 732 | + Vector mediaFormats = media.getMediaFormats(false); | |
| 733 | + if (mediaFormats.contains("8") || mediaFormats.contains("0")) { | |
| 734 | + port = media.getMediaPort(); | |
| 735 | + break; | |
| 736 | + } | |
| 737 | + } | |
| 738 | + logger.info("[TCP主动连接对方] serverGbId: {}, channelId: {}, 连接对方的地址:{}:{}, SSRC: {}, SSRC校验:{}", | |
| 739 | + platform.getServerGBId(), channelId, sdp.getConnection().getAddress(), port, ssrcInfo.getSsrc(), ssrcCheck); | |
| 740 | + JSONObject jsonObject = zlmresTfulUtils.connectRtpServer(mediaServerItem, sdp.getConnection().getAddress(), port, ssrcInfo.getStream()); | |
| 741 | + logger.info("[TCP主动连接对方] 结果: {}", jsonObject); | |
| 742 | + } catch (SdpException e) { | |
| 743 | + logger.error("[TCP主动连接对方] serverGbId: {}, channelId: {}, 解析200OK的SDP信息失败", platform.getServerGBId(), channelId, e); | |
| 744 | + dynamicTask.stop(timeOutTaskKey); | |
| 745 | + mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); | |
| 746 | + // 释放ssrc | |
| 747 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | |
| 748 | + | |
| 749 | + streamSession.remove(platform.getServerGBId(), channelId, ssrcInfo.getStream()); | |
| 750 | + | |
| 751 | + callback.run(InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(), | |
| 752 | + InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null); | |
| 753 | + inviteStreamService.call(InviteSessionType.PLAY, platform.getServerGBId(), channelId, null, | |
| 754 | + InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(), | |
| 755 | + InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null); | |
| 756 | + } | |
| 757 | + } | |
| 758 | + | |
| 759 | + @Override | |
| 760 | + public void stopBroadcast(ParentPlatform platform, DeviceChannel channel, String stream, boolean sendBye, MediaServerItem mediaServerItem) { | |
| 761 | + | |
| 762 | + try { | |
| 763 | + if (sendBye) { | |
| 764 | + commanderForPlatform.streamByeCmd(platform, channel.getChannelId(), stream, null, null); | |
| 765 | + } | |
| 766 | + } catch (InvalidArgumentException | SipException | ParseException | SsrcTransactionNotFoundException e) { | |
| 767 | + logger.warn("[消息发送失败] 停止语音对讲, 平台:{},通道:{}", platform.getId(), channel.getChannelId() ); | |
| 768 | + } finally { | |
| 769 | + mediaServerService.closeRTPServer(mediaServerItem, stream); | |
| 770 | + InviteInfo inviteInfo = inviteStreamService.getInviteInfo(null, platform.getServerGBId(), channel.getChannelId(), stream); | |
| 771 | + if (inviteInfo != null) { | |
| 772 | + // 释放ssrc | |
| 773 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), inviteInfo.getSsrcInfo().getSsrc()); | |
| 774 | + inviteStreamService.removeInviteInfo(inviteInfo); | |
| 775 | + } | |
| 776 | + streamSession.remove(platform.getServerGBId(), channel.getChannelId(), stream); | |
| 777 | + } | |
| 778 | + } | |
| 434 | 779 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
| ... | ... | @@ -8,19 +8,29 @@ import com.genersoft.iot.vmp.common.InviteSessionStatus; |
| 8 | 8 | import com.genersoft.iot.vmp.common.InviteSessionType; |
| 9 | 9 | import com.genersoft.iot.vmp.common.StreamInfo; |
| 10 | 10 | import com.genersoft.iot.vmp.conf.DynamicTask; |
| 11 | +import com.genersoft.iot.vmp.conf.SipConfig; | |
| 11 | 12 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 12 | 13 | import com.genersoft.iot.vmp.conf.exception.ControllerException; |
| 13 | 14 | import com.genersoft.iot.vmp.conf.exception.ServiceException; |
| 14 | 15 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; |
| 15 | 16 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 16 | 17 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| 18 | +import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; | |
| 19 | +import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; | |
| 17 | 20 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 21 | +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; | |
| 22 | +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | |
| 18 | 23 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; |
| 19 | 24 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; |
| 20 | 25 | import com.genersoft.iot.vmp.gb28181.utils.SipUtils; |
| 21 | 26 | import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; |
| 22 | 27 | import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; |
| 23 | 28 | import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; |
| 29 | +import com.genersoft.iot.vmp.media.zlm.dto.*; | |
| 30 | +import com.genersoft.iot.vmp.media.zlm.*; | |
| 31 | +import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; | |
| 32 | +import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; | |
| 33 | +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | |
| 24 | 34 | import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; |
| 25 | 35 | import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForRecordMp4; |
| 26 | 36 | import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; |
| ... | ... | @@ -29,19 +39,32 @@ import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam; |
| 29 | 39 | import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam; |
| 30 | 40 | import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; |
| 31 | 41 | import com.genersoft.iot.vmp.service.*; |
| 42 | +import com.genersoft.iot.vmp.service.bean.*; | |
| 43 | +import com.genersoft.iot.vmp.service.bean.ErrorCallback; | |
| 44 | +import com.genersoft.iot.vmp.service.bean.InviteErrorCode; | |
| 45 | +import com.genersoft.iot.vmp.service.bean.RequestPushStreamMsg; | |
| 46 | +import com.genersoft.iot.vmp.service.bean.SSRCInfo; | |
| 47 | +import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener; | |
| 32 | 48 | import com.genersoft.iot.vmp.service.bean.DownloadFileInfo; |
| 33 | 49 | import com.genersoft.iot.vmp.service.bean.ErrorCallback; |
| 34 | 50 | import com.genersoft.iot.vmp.service.bean.InviteErrorCode; |
| 35 | 51 | import com.genersoft.iot.vmp.service.bean.SSRCInfo; |
| 36 | 52 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 37 | 53 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 54 | +import com.genersoft.iot.vmp.storager.dao.CloudRecordServiceMapper; | |
| 38 | 55 | import com.genersoft.iot.vmp.utils.CloudRecordUtils; |
| 39 | 56 | import com.genersoft.iot.vmp.utils.DateUtil; |
| 57 | +import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; | |
| 40 | 58 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; |
| 59 | +import com.genersoft.iot.vmp.vmanager.bean.StreamContent; | |
| 60 | +import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioBroadcastEvent; | |
| 41 | 61 | import gov.nist.javax.sip.message.SIPResponse; |
| 42 | 62 | import org.slf4j.Logger; |
| 43 | 63 | import org.slf4j.LoggerFactory; |
| 44 | 64 | import org.springframework.beans.factory.annotation.Autowired; |
| 65 | +import org.springframework.beans.factory.annotation.Qualifier; | |
| 66 | +import org.springframework.data.redis.core.RedisTemplate; | |
| 67 | +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; | |
| 45 | 68 | import org.springframework.stereotype.Service; |
| 46 | 69 | import org.springframework.util.ObjectUtils; |
| 47 | 70 | |
| ... | ... | @@ -49,13 +72,12 @@ import javax.sdp.*; |
| 49 | 72 | import javax.sip.InvalidArgumentException; |
| 50 | 73 | import javax.sip.ResponseEvent; |
| 51 | 74 | import javax.sip.SipException; |
| 75 | +import javax.sip.header.CallIdHeader; | |
| 52 | 76 | import java.io.File; |
| 53 | 77 | import java.math.BigDecimal; |
| 54 | 78 | import java.math.RoundingMode; |
| 55 | 79 | import java.text.ParseException; |
| 56 | -import java.util.List; | |
| 57 | -import java.util.UUID; | |
| 58 | -import java.util.Vector; | |
| 80 | +import java.util.*; | |
| 59 | 81 | |
| 60 | 82 | @SuppressWarnings(value = {"rawtypes", "unchecked"}) |
| 61 | 83 | @Service |
| ... | ... | @@ -71,22 +93,31 @@ public class PlayServiceImpl implements IPlayService { |
| 71 | 93 | private ISIPCommander cmder; |
| 72 | 94 | |
| 73 | 95 | @Autowired |
| 74 | - private SIPCommanderFroPlatform sipCommanderFroPlatform; | |
| 96 | + private AudioBroadcastManager audioBroadcastManager; | |
| 97 | + | |
| 98 | + @Autowired | |
| 99 | + private IDeviceService deviceService; | |
| 100 | + | |
| 101 | + @Autowired | |
| 102 | + private ISIPCommanderForPlatform sipCommanderFroPlatform; | |
| 75 | 103 | |
| 76 | 104 | @Autowired |
| 77 | 105 | private IRedisCatchStorage redisCatchStorage; |
| 78 | 106 | |
| 79 | 107 | @Autowired |
| 108 | + private ZLMServerFactory zlmServerFactory; | |
| 109 | + | |
| 110 | + @Autowired | |
| 80 | 111 | private IInviteStreamService inviteStreamService; |
| 81 | 112 | |
| 82 | 113 | @Autowired |
| 83 | 114 | private ZlmHttpHookSubscribe subscribe; |
| 84 | 115 | |
| 85 | 116 | @Autowired |
| 86 | - private ZLMRESTfulUtils zlmresTfulUtils; | |
| 117 | + private SendRtpPortManager sendRtpPortManager; | |
| 87 | 118 | |
| 88 | 119 | @Autowired |
| 89 | - private ZLMServerFactory zlmServerFactory; | |
| 120 | + private ZLMRESTfulUtils zlmresTfulUtils; | |
| 90 | 121 | |
| 91 | 122 | @Autowired |
| 92 | 123 | private IMediaService mediaService; |
| ... | ... | @@ -98,17 +129,40 @@ public class PlayServiceImpl implements IPlayService { |
| 98 | 129 | private VideoStreamSessionManager streamSession; |
| 99 | 130 | |
| 100 | 131 | @Autowired |
| 101 | - private IDeviceService deviceService; | |
| 132 | + private UserSetting userSetting; | |
| 102 | 133 | |
| 103 | 134 | @Autowired |
| 104 | 135 | private IDeviceChannelService channelService; |
| 105 | 136 | |
| 106 | 137 | @Autowired |
| 107 | - private UserSetting userSetting; | |
| 138 | + private SipConfig sipConfig; | |
| 108 | 139 | |
| 109 | 140 | @Autowired |
| 110 | 141 | private DynamicTask dynamicTask; |
| 111 | 142 | |
| 143 | + @Autowired | |
| 144 | + private CloudRecordServiceMapper cloudRecordServiceMapper; | |
| 145 | + | |
| 146 | + @Autowired | |
| 147 | + private ISIPCommanderForPlatform commanderForPlatform; | |
| 148 | + | |
| 149 | + | |
| 150 | + @Qualifier("taskExecutor") | |
| 151 | + @Autowired | |
| 152 | + private ThreadPoolTaskExecutor taskExecutor; | |
| 153 | + | |
| 154 | + @Autowired | |
| 155 | + private RedisGbPlayMsgListener redisGbPlayMsgListener; | |
| 156 | + | |
| 157 | + @Autowired | |
| 158 | + private ZlmHttpHookSubscribe hookSubscribe; | |
| 159 | + | |
| 160 | + @Autowired | |
| 161 | + private SSRCFactory ssrcFactory; | |
| 162 | + | |
| 163 | + @Autowired | |
| 164 | + private RedisTemplate<Object, Object> redisTemplate; | |
| 165 | + | |
| 112 | 166 | |
| 113 | 167 | @Override |
| 114 | 168 | public SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback<Object> callback) { |
| ... | ... | @@ -166,7 +220,7 @@ public class PlayServiceImpl implements IPlayService { |
| 166 | 220 | } |
| 167 | 221 | } |
| 168 | 222 | String streamId = String.format("%s_%s", device.getDeviceId(), channelId);; |
| 169 | - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, ssrc, device.isSsrcCheck(), false, 0, false, device.getStreamModeForParam()); | |
| 223 | + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, ssrc, device.isSsrcCheck(), false, 0, false, false, device.getStreamModeForParam()); | |
| 170 | 224 | if (ssrcInfo == null) { |
| 171 | 225 | callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getMsg(), null); |
| 172 | 226 | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, |
| ... | ... | @@ -179,6 +233,147 @@ public class PlayServiceImpl implements IPlayService { |
| 179 | 233 | return ssrcInfo; |
| 180 | 234 | } |
| 181 | 235 | |
| 236 | + private void talk(MediaServerItem mediaServerItem, Device device, String channelId, String stream, | |
| 237 | + ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent, | |
| 238 | + Runnable timeoutCallback, AudioBroadcastEvent audioEvent) { | |
| 239 | + | |
| 240 | + String playSsrc = ssrcFactory.getPlaySsrc(mediaServerItem.getId()); | |
| 241 | + | |
| 242 | + if (playSsrc == null) { | |
| 243 | + audioEvent.call("ssrc已经用尽"); | |
| 244 | + return; | |
| 245 | + } | |
| 246 | + SendRtpItem sendRtpItem = new SendRtpItem(); | |
| 247 | + sendRtpItem.setApp("talk"); | |
| 248 | + sendRtpItem.setStream(stream); | |
| 249 | + sendRtpItem.setSsrc(playSsrc); | |
| 250 | + sendRtpItem.setDeviceId(device.getDeviceId()); | |
| 251 | + sendRtpItem.setPlatformId(device.getDeviceId()); | |
| 252 | + sendRtpItem.setChannelId(channelId); | |
| 253 | + sendRtpItem.setRtcp(false); | |
| 254 | + sendRtpItem.setMediaServerId(mediaServerItem.getId()); | |
| 255 | + sendRtpItem.setOnlyAudio(true); | |
| 256 | + sendRtpItem.setPlayType(InviteStreamType.TALK); | |
| 257 | + sendRtpItem.setPt(8); | |
| 258 | + sendRtpItem.setStatus(1); | |
| 259 | + sendRtpItem.setTcpActive(false); | |
| 260 | + sendRtpItem.setTcp(true); | |
| 261 | + sendRtpItem.setUsePs(false); | |
| 262 | + sendRtpItem.setReceiveStream(stream + "_talk"); | |
| 263 | + | |
| 264 | + String callId = SipUtils.getNewCallId(); | |
| 265 | + int port = sendRtpPortManager.getNextPort(mediaServerItem); | |
| 266 | + //端口获取失败的ssrcInfo 没有必要发送点播指令 | |
| 267 | + if (port <= 0) { | |
| 268 | + logger.info("[语音对讲] 端口分配异常,deviceId={},channelId={}", device.getDeviceId(), channelId); | |
| 269 | + audioEvent.call("端口分配异常"); | |
| 270 | + return; | |
| 271 | + } | |
| 272 | + sendRtpItem.setLocalPort(port); | |
| 273 | + sendRtpItem.setPort(port); | |
| 274 | + logger.info("[语音对讲]开始 deviceId: {}, channelId: {},收流端口: {}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, sendRtpItem.getLocalPort(), device.getStreamMode(), sendRtpItem.getSsrc(), false); | |
| 275 | + // 超时处理 | |
| 276 | + String timeOutTaskKey = UUID.randomUUID().toString(); | |
| 277 | + dynamicTask.startDelay(timeOutTaskKey, () -> { | |
| 278 | + | |
| 279 | + logger.info("[语音对讲] 收流超时 deviceId: {}, channelId: {},端口:{}, SSRC: {}", device.getDeviceId(), channelId, sendRtpItem.getPort(), sendRtpItem.getSsrc()); | |
| 280 | + timeoutCallback.run(); | |
| 281 | + // 点播超时回复BYE 同时释放ssrc以及此次点播的资源 | |
| 282 | + try { | |
| 283 | + cmder.streamByeCmd(device, channelId, sendRtpItem.getStream(), null); | |
| 284 | + } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) { | |
| 285 | + logger.error("[语音对讲]超时, 发送BYE失败 {}", e.getMessage()); | |
| 286 | + } finally { | |
| 287 | + timeoutCallback.run(); | |
| 288 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc()); | |
| 289 | + streamSession.remove(device.getDeviceId(), channelId, sendRtpItem.getStream()); | |
| 290 | + } | |
| 291 | + }, userSetting.getPlayTimeout()); | |
| 292 | + | |
| 293 | + Map<String, Object> param = new HashMap<>(12); | |
| 294 | + param.put("vhost","__defaultVhost__"); | |
| 295 | + param.put("app", sendRtpItem.getApp()); | |
| 296 | + param.put("stream", sendRtpItem.getStream()); | |
| 297 | + param.put("ssrc", sendRtpItem.getSsrc()); | |
| 298 | + param.put("src_port", sendRtpItem.getLocalPort()); | |
| 299 | + param.put("pt", sendRtpItem.getPt()); | |
| 300 | + param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0"); | |
| 301 | + param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0"); | |
| 302 | + param.put("is_udp", sendRtpItem.isTcp() ? "0" : "1"); | |
| 303 | + param.put("recv_stream_id", sendRtpItem.getReceiveStream()); | |
| 304 | + param.put("close_delay_ms", userSetting.getPlayTimeout() * 1000); | |
| 305 | + | |
| 306 | + zlmServerFactory.startSendRtpPassive(mediaServerItem, param, jsonObject -> { | |
| 307 | + if (jsonObject == null || jsonObject.getInteger("code") != 0 ) { | |
| 308 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc()); | |
| 309 | + logger.info("[语音对讲]失败 deviceId: {}, channelId: {}", device.getDeviceId(), channelId); | |
| 310 | + audioEvent.call("失败, " + jsonObject.getString("msg")); | |
| 311 | + // 查看是否已经建立了通道,存在则发送bye | |
| 312 | + stopTalk(device, channelId); | |
| 313 | + } | |
| 314 | + }); | |
| 315 | + | |
| 316 | + | |
| 317 | + // 查看设备是否已经在推流 | |
| 318 | + try { | |
| 319 | + cmder.talkStreamCmd(mediaServerItem, sendRtpItem, device, channelId, callId, (mediaServerItemInuse, hookParam) -> { | |
| 320 | + logger.info("[语音对讲] 流已生成, 开始推流: " + hookParam); | |
| 321 | + dynamicTask.stop(timeOutTaskKey); | |
| 322 | + // TODO 暂不做处理 | |
| 323 | + }, (mediaServerItemInuse, hookParam) -> { | |
| 324 | + logger.info("[语音对讲] 设备开始推流: " + hookParam); | |
| 325 | + dynamicTask.stop(timeOutTaskKey); | |
| 326 | + | |
| 327 | + }, (event) -> { | |
| 328 | + dynamicTask.stop(timeOutTaskKey); | |
| 329 | + | |
| 330 | + if (event.event instanceof ResponseEvent) { | |
| 331 | + ResponseEvent responseEvent = (ResponseEvent) event.event; | |
| 332 | + if (responseEvent.getResponse() instanceof SIPResponse) { | |
| 333 | + SIPResponse response = (SIPResponse) responseEvent.getResponse(); | |
| 334 | + sendRtpItem.setFromTag(response.getFromTag()); | |
| 335 | + sendRtpItem.setToTag(response.getToTag()); | |
| 336 | + sendRtpItem.setCallId(response.getCallIdHeader().getCallId()); | |
| 337 | + redisCatchStorage.updateSendRTPSever(sendRtpItem); | |
| 338 | + | |
| 339 | + streamSession.put(device.getDeviceId(), channelId, "talk", | |
| 340 | + sendRtpItem.getStream(), sendRtpItem.getSsrc(), sendRtpItem.getMediaServerId(), | |
| 341 | + response, InviteSessionType.TALK); | |
| 342 | + } else { | |
| 343 | + logger.error("[语音对讲]收到的消息错误,response不是SIPResponse"); | |
| 344 | + } | |
| 345 | + } else { | |
| 346 | + logger.error("[语音对讲]收到的消息错误,event不是ResponseEvent"); | |
| 347 | + } | |
| 348 | + | |
| 349 | + }, (event) -> { | |
| 350 | + dynamicTask.stop(timeOutTaskKey); | |
| 351 | + mediaServerService.closeRTPServer(mediaServerItem, sendRtpItem.getStream()); | |
| 352 | + // 释放ssrc | |
| 353 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc()); | |
| 354 | + streamSession.remove(device.getDeviceId(), channelId, sendRtpItem.getStream()); | |
| 355 | + errorEvent.response(event); | |
| 356 | + }); | |
| 357 | + } catch (InvalidArgumentException | SipException | ParseException e) { | |
| 358 | + | |
| 359 | + logger.error("[命令发送失败] 对讲消息: {}", e.getMessage()); | |
| 360 | + dynamicTask.stop(timeOutTaskKey); | |
| 361 | + mediaServerService.closeRTPServer(mediaServerItem, sendRtpItem.getStream()); | |
| 362 | + // 释放ssrc | |
| 363 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc()); | |
| 364 | + | |
| 365 | + streamSession.remove(device.getDeviceId(), channelId, sendRtpItem.getStream()); | |
| 366 | + SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(); | |
| 367 | + eventResult.type = SipSubscribe.EventResultType.cmdSendFailEvent; | |
| 368 | + eventResult.statusCode = -1; | |
| 369 | + eventResult.msg = "命令发送失败"; | |
| 370 | + errorEvent.response(eventResult); | |
| 371 | + } | |
| 372 | +// } | |
| 373 | + | |
| 374 | + } | |
| 375 | + | |
| 376 | + | |
| 182 | 377 | |
| 183 | 378 | @Override |
| 184 | 379 | public void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel, |
| ... | ... | @@ -343,7 +538,22 @@ public class PlayServiceImpl implements IPlayService { |
| 343 | 538 | } |
| 344 | 539 | logger.info("[TCP主动连接对方] deviceId: {}, channelId: {}, 连接对方的地址:{}:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, sdp.getConnection().getAddress(), port, device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck()); |
| 345 | 540 | JSONObject jsonObject = zlmresTfulUtils.connectRtpServer(mediaServerItem, sdp.getConnection().getAddress(), port, ssrcInfo.getStream()); |
| 346 | - logger.info("[TCP主动连接对方] 结果: {}", jsonObject); | |
| 541 | + logger.info("[TCP主动连接对方] 结果: {}" , jsonObject); | |
| 542 | + if (jsonObject.getInteger("code") != 0) { | |
| 543 | + // 主动连接失败,结束流程, 清理数据 | |
| 544 | + dynamicTask.stop(timeOutTaskKey); | |
| 545 | + mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); | |
| 546 | + // 释放ssrc | |
| 547 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | |
| 548 | + | |
| 549 | + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); | |
| 550 | + | |
| 551 | + callback.run(InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(), | |
| 552 | + InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null); | |
| 553 | + inviteStreamService.call(InviteSessionType.BROADCAST, device.getDeviceId(), channelId, null, | |
| 554 | + InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(), | |
| 555 | + InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null); | |
| 556 | + } | |
| 347 | 557 | } catch (SdpException e) { |
| 348 | 558 | logger.error("[TCP主动连接对方] deviceId: {}, channelId: {}, 解析200OK的SDP信息失败", device.getDeviceId(), channelId, e); |
| 349 | 559 | dynamicTask.stop(timeOutTaskKey); |
| ... | ... | @@ -355,7 +565,7 @@ public class PlayServiceImpl implements IPlayService { |
| 355 | 565 | |
| 356 | 566 | callback.run(InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(), |
| 357 | 567 | InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null); |
| 358 | - inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, | |
| 568 | + inviteStreamService.call(InviteSessionType.BROADCAST, device.getDeviceId(), channelId, null, | |
| 359 | 569 | InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(), |
| 360 | 570 | InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null); |
| 361 | 571 | } |
| ... | ... | @@ -383,7 +593,7 @@ public class PlayServiceImpl implements IPlayService { |
| 383 | 593 | zlmresTfulUtils.getSnap(mediaServerItemInuse, streamUrl, 15, 1, path, fileName); |
| 384 | 594 | } |
| 385 | 595 | |
| 386 | - private StreamInfo onPublishHandlerForPlay(MediaServerItem mediaServerItem, HookParam hookParam, String deviceId, String channelId) { | |
| 596 | + public StreamInfo onPublishHandlerForPlay(MediaServerItem mediaServerItem, HookParam hookParam, String deviceId, String channelId) { | |
| 387 | 597 | StreamInfo streamInfo = null; |
| 388 | 598 | Device device = redisCatchStorage.getDevice(deviceId); |
| 389 | 599 | OnStreamChangedHookParam streamChangedHookParam = (OnStreamChangedHookParam)hookParam; |
| ... | ... | @@ -466,7 +676,7 @@ public class PlayServiceImpl implements IPlayService { |
| 466 | 676 | .replace(":", "") |
| 467 | 677 | .replace(" ", ""); |
| 468 | 678 | String stream = deviceId + "_" + channelId + "_" + startTimeStr + "_" + endTimeTimeStr; |
| 469 | - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, stream, null, device.isSsrcCheck(), true, 0, false, device.getStreamModeForParam()); | |
| 679 | + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, stream, null, device.isSsrcCheck(), true, 0, false, false, device.getStreamModeForParam()); | |
| 470 | 680 | playBack(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, callback); |
| 471 | 681 | } |
| 472 | 682 | |
| ... | ... | @@ -659,7 +869,7 @@ public class PlayServiceImpl implements IPlayService { |
| 659 | 869 | return; |
| 660 | 870 | } |
| 661 | 871 | // 录像下载不使用固定流地址,固定流地址会导致如果开始时间与结束时间一致时文件错误的叠加在一起 |
| 662 | - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, null, device.isSsrcCheck(), true, 0, false, device.getStreamModeForParam()); | |
| 872 | + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, null, device.isSsrcCheck(), true, 0, false,false, device.getStreamModeForParam()); | |
| 663 | 873 | download(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, downloadSpeed, callback); |
| 664 | 874 | } |
| 665 | 875 | |
| ... | ... | @@ -899,6 +1109,142 @@ public class PlayServiceImpl implements IPlayService { |
| 899 | 1109 | } |
| 900 | 1110 | |
| 901 | 1111 | @Override |
| 1112 | + public AudioBroadcastResult audioBroadcast(Device device, String channelId, Boolean broadcastMode) { | |
| 1113 | + // TODO 必须多端口模式才支持语音喊话鹤语音对讲 | |
| 1114 | + if (device == null || channelId == null) { | |
| 1115 | + return null; | |
| 1116 | + } | |
| 1117 | + logger.info("[语音喊话] device: {}, channel: {}", device.getDeviceId(), channelId); | |
| 1118 | + DeviceChannel deviceChannel = storager.queryChannel(device.getDeviceId(), channelId); | |
| 1119 | + if (deviceChannel == null) { | |
| 1120 | + logger.warn("开启语音广播的时候未找到通道: {}", channelId); | |
| 1121 | + return null; | |
| 1122 | + } | |
| 1123 | + MediaServerItem mediaServerItem = mediaServerService.getMediaServerForMinimumLoad(null); | |
| 1124 | + if (broadcastMode == null) { | |
| 1125 | + broadcastMode = true; | |
| 1126 | + } | |
| 1127 | + String app = broadcastMode?"broadcast":"talk"; | |
| 1128 | + String stream = device.getDeviceId() + "_" + channelId; | |
| 1129 | + AudioBroadcastResult audioBroadcastResult = new AudioBroadcastResult(); | |
| 1130 | + audioBroadcastResult.setApp(app); | |
| 1131 | + audioBroadcastResult.setStream(stream); | |
| 1132 | + audioBroadcastResult.setStreamInfo(new StreamContent(mediaService.getStreamInfoByAppAndStream(mediaServerItem, app, stream, null, null, null, false))); | |
| 1133 | + audioBroadcastResult.setCodec("G.711"); | |
| 1134 | + return audioBroadcastResult; | |
| 1135 | + } | |
| 1136 | + | |
| 1137 | + @Override | |
| 1138 | + public boolean audioBroadcastCmd(Device device, String channelId, MediaServerItem mediaServerItem, String app, String stream, int timeout, boolean isFromPlatform, AudioBroadcastEvent event) throws InvalidArgumentException, ParseException, SipException { | |
| 1139 | + if (device == null || channelId == null) { | |
| 1140 | + return false; | |
| 1141 | + } | |
| 1142 | + logger.info("[语音喊话] device: {}, channel: {}", device.getDeviceId(), channelId); | |
| 1143 | + DeviceChannel deviceChannel = storager.queryChannel(device.getDeviceId(), channelId); | |
| 1144 | + if (deviceChannel == null) { | |
| 1145 | + logger.warn("开启语音广播的时候未找到通道: {}", channelId); | |
| 1146 | + event.call("开启语音广播的时候未找到通道"); | |
| 1147 | + return false; | |
| 1148 | + } | |
| 1149 | + // 查询通道使用状态 | |
| 1150 | + if (audioBroadcastManager.exit(device.getDeviceId(), channelId)) { | |
| 1151 | + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(device.getDeviceId(), channelId, null, null); | |
| 1152 | + if (sendRtpItem != null && sendRtpItem.isOnlyAudio()) { | |
| 1153 | + // 查询流是否存在,不存在则认为是异常状态 | |
| 1154 | + Boolean streamReady = zlmServerFactory.isStreamReady(mediaServerItem, sendRtpItem.getApp(), sendRtpItem.getStream()); | |
| 1155 | + if (streamReady) { | |
| 1156 | + logger.warn("语音广播已经开启: {}", channelId); | |
| 1157 | + event.call("语音广播已经开启"); | |
| 1158 | + return false; | |
| 1159 | + } else { | |
| 1160 | + stopAudioBroadcast(device.getDeviceId(), channelId); | |
| 1161 | + } | |
| 1162 | + } | |
| 1163 | + } | |
| 1164 | +// SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(device.getDeviceId(), channelId, null, null); | |
| 1165 | +// if (sendRtpItem != null) { | |
| 1166 | +// MediaServerItem mediaServer = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | |
| 1167 | +// Boolean streamReady = zlmServerFactory.isStreamReady(mediaServer, sendRtpItem.getApp(), sendRtpItem.getStream()); | |
| 1168 | +// if (streamReady) { | |
| 1169 | +// logger.warn("[语音对讲] 进行中: {}", channelId); | |
| 1170 | +// event.call("语音对讲进行中"); | |
| 1171 | +// return false; | |
| 1172 | +// } else { | |
| 1173 | +// stopTalk(device, channelId); | |
| 1174 | +// } | |
| 1175 | +// } | |
| 1176 | + | |
| 1177 | + // 发送通知 | |
| 1178 | + cmder.audioBroadcastCmd(device, channelId, eventResultForOk -> { | |
| 1179 | + // 发送成功 | |
| 1180 | + AudioBroadcastCatch audioBroadcastCatch = new AudioBroadcastCatch(device.getDeviceId(), channelId, mediaServerItem, app, stream, event, AudioBroadcastCatchStatus.Ready, isFromPlatform); | |
| 1181 | + audioBroadcastManager.update(audioBroadcastCatch); | |
| 1182 | + }, eventResultForError -> { | |
| 1183 | + // 发送失败 | |
| 1184 | + logger.error("语音广播发送失败: {}:{}", channelId, eventResultForError.msg); | |
| 1185 | + event.call("语音广播发送失败"); | |
| 1186 | + stopAudioBroadcast(device.getDeviceId(), channelId); | |
| 1187 | + }); | |
| 1188 | + return true; | |
| 1189 | + } | |
| 1190 | + | |
| 1191 | + @Override | |
| 1192 | + public boolean audioBroadcastInUse(Device device, String channelId) { | |
| 1193 | + if (audioBroadcastManager.exit(device.getDeviceId(), channelId)) { | |
| 1194 | + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(device.getDeviceId(), channelId, null, null); | |
| 1195 | + if (sendRtpItem != null && sendRtpItem.isOnlyAudio()) { | |
| 1196 | + // 查询流是否存在,不存在则认为是异常状态 | |
| 1197 | + MediaServerItem mediaServerServiceOne = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | |
| 1198 | + Boolean streamReady = zlmServerFactory.isStreamReady(mediaServerServiceOne, sendRtpItem.getApp(), sendRtpItem.getStream()); | |
| 1199 | + if (streamReady) { | |
| 1200 | + logger.warn("语音广播通道使用中: {}", channelId); | |
| 1201 | + return true; | |
| 1202 | + } | |
| 1203 | + } | |
| 1204 | + } | |
| 1205 | + return false; | |
| 1206 | + } | |
| 1207 | + | |
| 1208 | + | |
| 1209 | + @Override | |
| 1210 | + public void stopAudioBroadcast(String deviceId, String channelId) { | |
| 1211 | + logger.info("[停止对讲] 设备:{}, 通道:{}", deviceId, channelId); | |
| 1212 | + List<AudioBroadcastCatch> audioBroadcastCatchList = new ArrayList<>(); | |
| 1213 | + if (channelId == null) { | |
| 1214 | + audioBroadcastCatchList.addAll(audioBroadcastManager.get(deviceId)); | |
| 1215 | + } else { | |
| 1216 | + audioBroadcastCatchList.add(audioBroadcastManager.get(deviceId, channelId)); | |
| 1217 | + } | |
| 1218 | + if (audioBroadcastCatchList.size() > 0) { | |
| 1219 | + for (AudioBroadcastCatch audioBroadcastCatch : audioBroadcastCatchList) { | |
| 1220 | + Device device = deviceService.getDevice(deviceId); | |
| 1221 | + if (device == null || audioBroadcastCatch == null) { | |
| 1222 | + return; | |
| 1223 | + } | |
| 1224 | + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(deviceId, audioBroadcastCatch.getChannelId(), null, null); | |
| 1225 | + if (sendRtpItem != null) { | |
| 1226 | + redisCatchStorage.deleteSendRTPServer(deviceId, sendRtpItem.getChannelId(), null, null); | |
| 1227 | + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | |
| 1228 | + Map<String, Object> param = new HashMap<>(); | |
| 1229 | + param.put("vhost", "__defaultVhost__"); | |
| 1230 | + param.put("app", sendRtpItem.getApp()); | |
| 1231 | + param.put("stream", sendRtpItem.getStream()); | |
| 1232 | + zlmresTfulUtils.stopSendRtp(mediaInfo, param); | |
| 1233 | + try { | |
| 1234 | + cmder.streamByeCmdForDeviceInvite(device, sendRtpItem.getChannelId(), audioBroadcastCatch.getSipTransactionInfo(), null); | |
| 1235 | + } catch (InvalidArgumentException | ParseException | SipException | | |
| 1236 | + SsrcTransactionNotFoundException e) { | |
| 1237 | + logger.error("[消息发送失败] 发送语音喊话BYE失败"); | |
| 1238 | + } | |
| 1239 | + } | |
| 1240 | + | |
| 1241 | + audioBroadcastManager.del(deviceId, channelId); | |
| 1242 | + } | |
| 1243 | + } | |
| 1244 | + } | |
| 1245 | + | |
| 1246 | + | |
| 1247 | + @Override | |
| 902 | 1248 | public void zlmServerOnline(String mediaServerId) { |
| 903 | 1249 | // TODO 查找之前的点播,流如果不存在则给下级发送bye |
| 904 | 1250 | // MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); |
| ... | ... | @@ -1007,6 +1353,199 @@ public class PlayServiceImpl implements IPlayService { |
| 1007 | 1353 | } |
| 1008 | 1354 | |
| 1009 | 1355 | @Override |
| 1356 | + public void startPushStream(SendRtpItem sendRtpItem, SIPResponse sipResponse, ParentPlatform platform, CallIdHeader callIdHeader) { | |
| 1357 | + // 开始发流 | |
| 1358 | + String is_Udp = sendRtpItem.isTcp() ? "0" : "1"; | |
| 1359 | + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | |
| 1360 | + logger.info("[开始推流] rtp/{}, 目标={}:{},SSRC={}, RTCP={}", sendRtpItem.getStream(), | |
| 1361 | + sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isRtcp()); | |
| 1362 | + Map<String, Object> param = new HashMap<>(12); | |
| 1363 | + param.put("vhost", "__defaultVhost__"); | |
| 1364 | + param.put("app", sendRtpItem.getApp()); | |
| 1365 | + param.put("stream", sendRtpItem.getStream()); | |
| 1366 | + param.put("ssrc", sendRtpItem.getSsrc()); | |
| 1367 | + param.put("src_port", sendRtpItem.getLocalPort()); | |
| 1368 | + param.put("pt", sendRtpItem.getPt()); | |
| 1369 | + param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0"); | |
| 1370 | + param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0"); | |
| 1371 | + param.put("is_udp", is_Udp); | |
| 1372 | + if (!sendRtpItem.isTcp()) { | |
| 1373 | + // udp模式下开启rtcp保活 | |
| 1374 | + param.put("udp_rtcp_timeout", sendRtpItem.isRtcp() ? "1" : "0"); | |
| 1375 | + } | |
| 1376 | + | |
| 1377 | + if (mediaInfo == null) { | |
| 1378 | + RequestPushStreamMsg requestPushStreamMsg = RequestPushStreamMsg.getInstance( | |
| 1379 | + sendRtpItem.getMediaServerId(), sendRtpItem.getApp(), sendRtpItem.getStream(), | |
| 1380 | + sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isTcp(), | |
| 1381 | + sendRtpItem.getLocalPort(), sendRtpItem.getPt(), sendRtpItem.isUsePs(), sendRtpItem.isOnlyAudio()); | |
| 1382 | + redisGbPlayMsgListener.sendMsgForStartSendRtpStream(sendRtpItem.getServerId(), requestPushStreamMsg, json -> { | |
| 1383 | + startSendRtpStreamHand(sendRtpItem, platform, json, param, callIdHeader); | |
| 1384 | + }); | |
| 1385 | + } else { | |
| 1386 | + // 如果是严格模式,需要关闭端口占用 | |
| 1387 | + JSONObject startSendRtpStreamResult = null; | |
| 1388 | + if (sendRtpItem.getLocalPort() != 0) { | |
| 1389 | + if (sendRtpItem.isTcpActive()) { | |
| 1390 | + startSendRtpStreamResult = zlmServerFactory.startSendRtpPassive(mediaInfo, param); | |
| 1391 | + } else { | |
| 1392 | + param.put("dst_url", sendRtpItem.getIp()); | |
| 1393 | + param.put("dst_port", sendRtpItem.getPort()); | |
| 1394 | + startSendRtpStreamResult = zlmServerFactory.startSendRtpStream(mediaInfo, param); | |
| 1395 | + } | |
| 1396 | + } else { | |
| 1397 | + if (sendRtpItem.isTcpActive()) { | |
| 1398 | + startSendRtpStreamResult = zlmServerFactory.startSendRtpPassive(mediaInfo, param); | |
| 1399 | + } else { | |
| 1400 | + param.put("dst_url", sendRtpItem.getIp()); | |
| 1401 | + param.put("dst_port", sendRtpItem.getPort()); | |
| 1402 | + startSendRtpStreamResult = zlmServerFactory.startSendRtpStream(mediaInfo, param); | |
| 1403 | + } | |
| 1404 | + } | |
| 1405 | + if (startSendRtpStreamResult != null) { | |
| 1406 | + startSendRtpStreamHand(sendRtpItem, platform, startSendRtpStreamResult, param, callIdHeader); | |
| 1407 | + } | |
| 1408 | + } | |
| 1409 | + } | |
| 1410 | + | |
| 1411 | + @Override | |
| 1412 | + public void startSendRtpStreamHand(SendRtpItem sendRtpItem, Object correlationInfo, | |
| 1413 | + JSONObject jsonObject, Map<String, Object> param, CallIdHeader callIdHeader) { | |
| 1414 | + if (jsonObject == null) { | |
| 1415 | + logger.error("RTP推流失败: 请检查ZLM服务"); | |
| 1416 | + } else if (jsonObject.getInteger("code") == 0) { | |
| 1417 | + logger.info("调用ZLM推流接口, 结果: {}", jsonObject); | |
| 1418 | + logger.info("RTP推流成功[ {}/{} ],{}->{}, ", param.get("app"), param.get("stream"), jsonObject.getString("local_port"), | |
| 1419 | + sendRtpItem.isTcpActive()?"被动发流": param.get("dst_url") + ":" + param.get("dst_port")); | |
| 1420 | + } else { | |
| 1421 | + logger.error("RTP推流失败: {}, 参数:{}", jsonObject.getString("msg"), JSONObject.toJSONString(param)); | |
| 1422 | + if (sendRtpItem.isOnlyAudio()) { | |
| 1423 | + Device device = deviceService.getDevice(sendRtpItem.getDeviceId()); | |
| 1424 | + AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); | |
| 1425 | + if (audioBroadcastCatch != null) { | |
| 1426 | + try { | |
| 1427 | + cmder.streamByeCmd(device, sendRtpItem.getChannelId(), audioBroadcastCatch.getSipTransactionInfo(), null); | |
| 1428 | + } catch (SipException | ParseException | InvalidArgumentException | | |
| 1429 | + SsrcTransactionNotFoundException e) { | |
| 1430 | + logger.error("[命令发送失败] 停止语音对讲: {}", e.getMessage()); | |
| 1431 | + } | |
| 1432 | + } | |
| 1433 | + } else { | |
| 1434 | + // 向上级平台 | |
| 1435 | + if (correlationInfo instanceof ParentPlatform) { | |
| 1436 | + try { | |
| 1437 | + ParentPlatform parentPlatform = (ParentPlatform)correlationInfo; | |
| 1438 | + commanderForPlatform.streamByeCmd(parentPlatform, callIdHeader.getCallId()); | |
| 1439 | + } catch (SipException | InvalidArgumentException | ParseException e) { | |
| 1440 | + logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage()); | |
| 1441 | + } | |
| 1442 | + } | |
| 1443 | + } | |
| 1444 | + } | |
| 1445 | + } | |
| 1446 | + | |
| 1447 | + @Override | |
| 1448 | + public void talkCmd(Device device, String channelId, MediaServerItem mediaServerItem, String stream, AudioBroadcastEvent event) { | |
| 1449 | + if (device == null || channelId == null) { | |
| 1450 | + return; | |
| 1451 | + } | |
| 1452 | + // TODO 必须多端口模式才支持语音喊话鹤语音对讲 | |
| 1453 | + logger.info("[语音对讲] device: {}, channel: {}", device.getDeviceId(), channelId); | |
| 1454 | + DeviceChannel deviceChannel = storager.queryChannel(device.getDeviceId(), channelId); | |
| 1455 | + if (deviceChannel == null) { | |
| 1456 | + logger.warn("开启语音对讲的时候未找到通道: {}", channelId); | |
| 1457 | + event.call("开启语音对讲的时候未找到通道"); | |
| 1458 | + return; | |
| 1459 | + } | |
| 1460 | + // 查询通道使用状态 | |
| 1461 | + if (audioBroadcastManager.exit(device.getDeviceId(), channelId)) { | |
| 1462 | + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(device.getDeviceId(), channelId, null, null); | |
| 1463 | + if (sendRtpItem != null && sendRtpItem.isOnlyAudio()) { | |
| 1464 | + // 查询流是否存在,不存在则认为是异常状态 | |
| 1465 | + MediaServerItem mediaServer = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | |
| 1466 | + Boolean streamReady = zlmServerFactory.isStreamReady(mediaServer, sendRtpItem.getApp(), sendRtpItem.getStream()); | |
| 1467 | + if (streamReady) { | |
| 1468 | + logger.warn("[语音对讲] 正在语音广播,无法开启语音通话: {}", channelId); | |
| 1469 | + event.call("正在语音广播"); | |
| 1470 | + return; | |
| 1471 | + } else { | |
| 1472 | + stopAudioBroadcast(device.getDeviceId(), channelId); | |
| 1473 | + } | |
| 1474 | + } | |
| 1475 | + } | |
| 1476 | + | |
| 1477 | + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(device.getDeviceId(), channelId, stream, null); | |
| 1478 | + if (sendRtpItem != null) { | |
| 1479 | + MediaServerItem mediaServer = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | |
| 1480 | + Boolean streamReady = zlmServerFactory.isStreamReady(mediaServer, "rtp", sendRtpItem.getReceiveStream()); | |
| 1481 | + if (streamReady) { | |
| 1482 | + logger.warn("[语音对讲] 进行中: {}", channelId); | |
| 1483 | + event.call("语音对讲进行中"); | |
| 1484 | + return; | |
| 1485 | + } else { | |
| 1486 | + stopTalk(device, channelId); | |
| 1487 | + } | |
| 1488 | + } | |
| 1489 | + | |
| 1490 | + talk(mediaServerItem, device, channelId, stream, (mediaServerItem1, hookParam) -> { | |
| 1491 | + logger.info("[语音对讲] 收到设备发来的流"); | |
| 1492 | + }, eventResult -> { | |
| 1493 | + logger.warn("[语音对讲] 失败,{}/{}, 错误码 {} {}", device.getDeviceId(), channelId, eventResult.statusCode, eventResult.msg); | |
| 1494 | + event.call("失败,错误码 " + eventResult.statusCode + ", " + eventResult.msg); | |
| 1495 | + }, () -> { | |
| 1496 | + logger.warn("[语音对讲] 失败,{}/{} 超时", device.getDeviceId(), channelId); | |
| 1497 | + event.call("失败,超时 "); | |
| 1498 | + stopTalk(device, channelId); | |
| 1499 | + }, errorMsg -> { | |
| 1500 | + logger.warn("[语音对讲] 失败,{}/{} {}", device.getDeviceId(), channelId, errorMsg); | |
| 1501 | + event.call(errorMsg); | |
| 1502 | + stopTalk(device, channelId); | |
| 1503 | + }); | |
| 1504 | + } | |
| 1505 | + | |
| 1506 | + private void stopTalk(Device device, String channelId) { | |
| 1507 | + stopTalk(device, channelId, null); | |
| 1508 | + } | |
| 1509 | + | |
| 1510 | + @Override | |
| 1511 | + public void stopTalk(Device device, String channelId, Boolean streamIsReady) { | |
| 1512 | + logger.info("[语音对讲] 停止, {}/{}", device.getDeviceId(), channelId); | |
| 1513 | + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(device.getDeviceId(), channelId, null, null); | |
| 1514 | + if (sendRtpItem == null) { | |
| 1515 | + logger.info("[语音对讲] 停止失败, 未找到发送信息,可能已经停止"); | |
| 1516 | + return; | |
| 1517 | + } | |
| 1518 | + // 停止向设备推流 | |
| 1519 | + String mediaServerId = sendRtpItem.getMediaServerId(); | |
| 1520 | + if (mediaServerId == null) { | |
| 1521 | + return; | |
| 1522 | + } | |
| 1523 | + | |
| 1524 | + MediaServerItem mediaServer = mediaServerService.getOne(mediaServerId); | |
| 1525 | + | |
| 1526 | + if (streamIsReady == null || streamIsReady) { | |
| 1527 | + Map<String, Object> param = new HashMap<>(); | |
| 1528 | + param.put("vhost", "__defaultVhost__"); | |
| 1529 | + param.put("app", sendRtpItem.getApp()); | |
| 1530 | + param.put("stream", sendRtpItem.getStream()); | |
| 1531 | + param.put("ssrc", sendRtpItem.getSsrc()); | |
| 1532 | + zlmServerFactory.stopSendRtpStream(mediaServer, param); | |
| 1533 | + } | |
| 1534 | + | |
| 1535 | + ssrcFactory.releaseSsrc(mediaServerId, sendRtpItem.getSsrc()); | |
| 1536 | + | |
| 1537 | + SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, null, sendRtpItem.getStream()); | |
| 1538 | + if (ssrcTransaction != null) { | |
| 1539 | + try { | |
| 1540 | + cmder.streamByeCmd(device, channelId, sendRtpItem.getStream(), null); | |
| 1541 | + } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) { | |
| 1542 | + logger.info("[语音对讲] 停止消息发送失败,可能已经停止"); | |
| 1543 | + } | |
| 1544 | + } | |
| 1545 | + redisCatchStorage.deleteSendRTPServer(device.getDeviceId(), channelId,null, null); | |
| 1546 | + } | |
| 1547 | + | |
| 1548 | + @Override | |
| 1010 | 1549 | public void getSnap(String deviceId, String channelId, String fileName, ErrorCallback errorCallback) { |
| 1011 | 1550 | Device device = deviceService.getDevice(deviceId); |
| 1012 | 1551 | if (device == null) { | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
| ... | ... | @@ -90,12 +90,6 @@ public class StreamProxyServiceImpl implements IStreamProxyService { |
| 90 | 90 | private PlatformGbStreamMapper platformGbStreamMapper; |
| 91 | 91 | |
| 92 | 92 | @Autowired |
| 93 | - private EventPublisher eventPublisher; | |
| 94 | - | |
| 95 | - @Autowired | |
| 96 | - private ParentPlatformMapper parentPlatformMapper; | |
| 97 | - | |
| 98 | - @Autowired | |
| 99 | 93 | private IGbStreamService gbStreamService; |
| 100 | 94 | |
| 101 | 95 | @Autowired | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamCloseResponseListener.java
| ... | ... | @@ -79,7 +79,7 @@ public class RedisPushStreamCloseResponseListener implements MessageListener { |
| 79 | 79 | for (SendRtpItem sendRtpItem : sendRtpItems) { |
| 80 | 80 | ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId()); |
| 81 | 81 | if (parentPlatform != null) { |
| 82 | - redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(), sendRtpItem.getCallId(), sendRtpItem.getStreamId()); | |
| 82 | + redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(), sendRtpItem.getCallId(), sendRtpItem.getStream()); | |
| 83 | 83 | try { |
| 84 | 84 | commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem); |
| 85 | 85 | } catch (SipException | InvalidArgumentException | ParseException e) { |
| ... | ... | @@ -88,7 +88,7 @@ public class RedisPushStreamCloseResponseListener implements MessageListener { |
| 88 | 88 | } |
| 89 | 89 | if (push.isSelf()) { |
| 90 | 90 | // 停止向上级推流 |
| 91 | - String streamId = sendRtpItem.getStreamId(); | |
| 91 | + String streamId = sendRtpItem.getStream(); | |
| 92 | 92 | Map<String, Object> param = new HashMap<>(); |
| 93 | 93 | param.put("vhost","__defaultVhost__"); |
| 94 | 94 | param.put("app",sendRtpItem.getApp()); |
| ... | ... | @@ -96,11 +96,11 @@ public class RedisPushStreamCloseResponseListener implements MessageListener { |
| 96 | 96 | param.put("ssrc",sendRtpItem.getSsrc()); |
| 97 | 97 | logger.info("[REDIS消息-推流结束] 停止向上级推流:{}", streamId); |
| 98 | 98 | MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); |
| 99 | - redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(), sendRtpItem.getCallId(), sendRtpItem.getStreamId()); | |
| 99 | + redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(), sendRtpItem.getCallId(), sendRtpItem.getStream()); | |
| 100 | 100 | zlmServerFactory.stopSendRtpStream(mediaInfo, param); |
| 101 | 101 | if (InviteStreamType.PUSH == sendRtpItem.getPlayType()) { |
| 102 | 102 | MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, |
| 103 | - sendRtpItem.getApp(), sendRtpItem.getStreamId(), sendRtpItem.getChannelId(), | |
| 103 | + sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getChannelId(), | |
| 104 | 104 | sendRtpItem.getPlatformId(), parentPlatform.getName(), userSetting.getServerId(), sendRtpItem.getMediaServerId()); |
| 105 | 105 | messageForPushChannel.setPlatFormIndex(parentPlatform.getId()); |
| 106 | 106 | redisCatchStorage.sendPlatformStopPlayMsg(messageForPushChannel); | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java
| ... | ... | @@ -43,6 +43,7 @@ public interface DeviceMapper { |
| 43 | 43 | "geo_coord_sys," + |
| 44 | 44 | "on_line," + |
| 45 | 45 | "media_server_id," + |
| 46 | + "broadcast_push_after_ack," + | |
| 46 | 47 | "(SELECT count(0) FROM wvp_device_channel WHERE device_id=wvp_device.device_id) as channel_count "+ |
| 47 | 48 | " FROM wvp_device WHERE device_id = #{deviceId}") |
| 48 | 49 | Device getDeviceByDeviceId(String deviceId); |
| ... | ... | @@ -73,6 +74,7 @@ public interface DeviceMapper { |
| 73 | 74 | "subscribe_cycle_for_alarm,"+ |
| 74 | 75 | "ssrc_check,"+ |
| 75 | 76 | "as_message_channel,"+ |
| 77 | + "broadcast_push_after_ack,"+ | |
| 76 | 78 | "geo_coord_sys,"+ |
| 77 | 79 | "on_line"+ |
| 78 | 80 | ") VALUES (" + |
| ... | ... | @@ -101,6 +103,7 @@ public interface DeviceMapper { |
| 101 | 103 | "#{subscribeCycleForAlarm}," + |
| 102 | 104 | "#{ssrcCheck}," + |
| 103 | 105 | "#{asMessageChannel}," + |
| 106 | + "#{broadcastPushAfterAck}," + | |
| 104 | 107 | "#{geoCoordSys}," + |
| 105 | 108 | "#{onLine}" + |
| 106 | 109 | ")") |
| ... | ... | @@ -155,6 +158,7 @@ public interface DeviceMapper { |
| 155 | 158 | "subscribe_cycle_for_alarm,"+ |
| 156 | 159 | "ssrc_check,"+ |
| 157 | 160 | "as_message_channel,"+ |
| 161 | + "broadcast_push_after_ack,"+ | |
| 158 | 162 | "geo_coord_sys,"+ |
| 159 | 163 | "on_line,"+ |
| 160 | 164 | "media_server_id,"+ |
| ... | ... | @@ -195,6 +199,7 @@ public interface DeviceMapper { |
| 195 | 199 | "subscribe_cycle_for_alarm,"+ |
| 196 | 200 | "ssrc_check,"+ |
| 197 | 201 | "as_message_channel,"+ |
| 202 | + "broadcast_push_after_ack,"+ | |
| 198 | 203 | "geo_coord_sys,"+ |
| 199 | 204 | "on_line"+ |
| 200 | 205 | " FROM wvp_device WHERE on_line = true") |
| ... | ... | @@ -225,6 +230,7 @@ public interface DeviceMapper { |
| 225 | 230 | "subscribe_cycle_for_alarm,"+ |
| 226 | 231 | "ssrc_check,"+ |
| 227 | 232 | "as_message_channel,"+ |
| 233 | + "broadcast_push_after_ack,"+ | |
| 228 | 234 | "geo_coord_sys,"+ |
| 229 | 235 | "on_line"+ |
| 230 | 236 | " FROM wvp_device WHERE ip = #{host} AND port=#{port}") |
| ... | ... | @@ -246,6 +252,7 @@ public interface DeviceMapper { |
| 246 | 252 | "<if test=\"subscribeCycleForAlarm != null\">, subscribe_cycle_for_alarm=#{subscribeCycleForAlarm}</if>" + |
| 247 | 253 | "<if test=\"ssrcCheck != null\">, ssrc_check=#{ssrcCheck}</if>" + |
| 248 | 254 | "<if test=\"asMessageChannel != null\">, as_message_channel=#{asMessageChannel}</if>" + |
| 255 | + "<if test=\"broadcastPushAfterAck != null\">, broadcast_push_after_ack=#{broadcastPushAfterAck}</if>" + | |
| 249 | 256 | "<if test=\"geoCoordSys != null\">, geo_coord_sys=#{geoCoordSys}</if>" + |
| 250 | 257 | "<if test=\"mediaServerId != null\">, media_server_id=#{mediaServerId}</if>" + |
| 251 | 258 | "WHERE device_id=#{deviceId}"+ |
| ... | ... | @@ -262,6 +269,7 @@ public interface DeviceMapper { |
| 262 | 269 | "charset,"+ |
| 263 | 270 | "ssrc_check,"+ |
| 264 | 271 | "as_message_channel,"+ |
| 272 | + "broadcastPushAfterAck,"+ | |
| 265 | 273 | "geo_coord_sys,"+ |
| 266 | 274 | "on_line,"+ |
| 267 | 275 | "media_server_id"+ |
| ... | ... | @@ -275,6 +283,7 @@ public interface DeviceMapper { |
| 275 | 283 | "#{charset}," + |
| 276 | 284 | "#{ssrcCheck}," + |
| 277 | 285 | "#{asMessageChannel}," + |
| 286 | + "#{broadcastPushAfterAck}," + | |
| 278 | 287 | "#{geoCoordSys}," + |
| 279 | 288 | "#{onLine}," + |
| 280 | 289 | "#{mediaServerId}" + | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
| ... | ... | @@ -150,7 +150,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { |
| 150 | 150 | + sendRtpItem.getMediaServerId() + "_" |
| 151 | 151 | + sendRtpItem.getPlatformId() + "_" |
| 152 | 152 | + sendRtpItem.getChannelId() + "_" |
| 153 | - + sendRtpItem.getStreamId() + "_" | |
| 153 | + + sendRtpItem.getStream() + "_" | |
| 154 | 154 | + sendRtpItem.getCallId(); |
| 155 | 155 | redisTemplate.opsForValue().set(key, sendRtpItem); |
| 156 | 156 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java
| ... | ... | @@ -96,12 +96,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { |
| 96 | 96 | @Autowired |
| 97 | 97 | private PlatformGbStreamMapper platformGbStreamMapper; |
| 98 | 98 | |
| 99 | - @Autowired | |
| 100 | - private IGbStreamService gbStreamService; | |
| 101 | - | |
| 102 | - @Autowired | |
| 103 | - private ParentPlatformMapper parentPlatformMapper; | |
| 104 | - | |
| 105 | 99 | /** |
| 106 | 100 | * 根据设备ID判断设备是否存在 |
| 107 | 101 | * | ... | ... |
src/main/java/com/genersoft/iot/vmp/vmanager/bean/AudioBroadcastResult.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.vmanager.bean; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * @author lin | |
| 5 | + */ | |
| 6 | +public class AudioBroadcastResult { | |
| 7 | + /** | |
| 8 | + * 推流的各个方式流地址 | |
| 9 | + */ | |
| 10 | + private StreamContent streamInfo; | |
| 11 | + | |
| 12 | + /** | |
| 13 | + * 编码格式 | |
| 14 | + */ | |
| 15 | + private String codec; | |
| 16 | + | |
| 17 | + /** | |
| 18 | + * 向zlm推流的应用名 | |
| 19 | + */ | |
| 20 | + private String app; | |
| 21 | + | |
| 22 | + /** | |
| 23 | + * 向zlm推流的流ID | |
| 24 | + */ | |
| 25 | + private String stream; | |
| 26 | + | |
| 27 | + | |
| 28 | + public StreamContent getStreamInfo() { | |
| 29 | + return streamInfo; | |
| 30 | + } | |
| 31 | + | |
| 32 | + public void setStreamInfo(StreamContent streamInfo) { | |
| 33 | + this.streamInfo = streamInfo; | |
| 34 | + } | |
| 35 | + | |
| 36 | + public String getCodec() { | |
| 37 | + return codec; | |
| 38 | + } | |
| 39 | + | |
| 40 | + public void setCodec(String codec) { | |
| 41 | + this.codec = codec; | |
| 42 | + } | |
| 43 | + | |
| 44 | + public String getApp() { | |
| 45 | + return app; | |
| 46 | + } | |
| 47 | + | |
| 48 | + public void setApp(String app) { | |
| 49 | + this.app = app; | |
| 50 | + } | |
| 51 | + | |
| 52 | + public String getStream() { | |
| 53 | + return stream; | |
| 54 | + } | |
| 55 | + | |
| 56 | + public void setStream(String stream) { | |
| 57 | + this.stream = stream; | |
| 58 | + } | |
| 59 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
| ... | ... | @@ -26,6 +26,7 @@ import com.genersoft.iot.vmp.service.bean.InviteErrorCode; |
| 26 | 26 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 27 | 27 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 28 | 28 | import com.genersoft.iot.vmp.utils.DateUtil; |
| 29 | +import com.genersoft.iot.vmp.vmanager.bean.*; | |
| 29 | 30 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; |
| 30 | 31 | import com.genersoft.iot.vmp.vmanager.bean.StreamContent; |
| 31 | 32 | import com.genersoft.iot.vmp.vmanager.bean.WVPResult; |
| ... | ... | @@ -48,6 +49,10 @@ import java.text.ParseException; |
| 48 | 49 | import java.util.List; |
| 49 | 50 | import java.util.UUID; |
| 50 | 51 | |
| 52 | + | |
| 53 | +/** | |
| 54 | + * @author lin | |
| 55 | + */ | |
| 51 | 56 | @Tag(name = "国标设备点播") |
| 52 | 57 | |
| 53 | 58 | @RestController |
| ... | ... | @@ -271,68 +276,42 @@ public class PlayController { |
| 271 | 276 | |
| 272 | 277 | @Operation(summary = "语音广播命令", security = @SecurityRequirement(name = JwtUtils.HEADER)) |
| 273 | 278 | @Parameter(name = "deviceId", description = "设备国标编号", required = true) |
| 274 | - @GetMapping("/broadcast/{deviceId}") | |
| 275 | - @PostMapping("/broadcast/{deviceId}") | |
| 276 | - public DeferredResult<String> broadcastApi(@PathVariable String deviceId) { | |
| 277 | - if (logger.isDebugEnabled()) { | |
| 278 | - logger.debug("语音广播API调用"); | |
| 279 | - } | |
| 280 | - Device device = storager.queryVideoDevice(deviceId); | |
| 281 | - DeferredResult<String> result = new DeferredResult<>(3 * 1000L); | |
| 282 | - String key = DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId; | |
| 283 | - if (resultHolder.exist(key, null)) { | |
| 284 | - result.setResult("设备使用中"); | |
| 285 | - return result; | |
| 279 | + @Parameter(name = "deviceId", description = "通道国标编号", required = true) | |
| 280 | + @Parameter(name = "timeout", description = "推流超时时间(秒)", required = true) | |
| 281 | + @GetMapping("/broadcast/{deviceId}/{channelId}") | |
| 282 | + @PostMapping("/broadcast/{deviceId}/{channelId}") | |
| 283 | + public AudioBroadcastResult broadcastApi(@PathVariable String deviceId, @PathVariable String channelId, Integer timeout, Boolean broadcastMode) { | |
| 284 | + if (logger.isDebugEnabled()) { | |
| 285 | + logger.debug("语音广播API调用"); | |
| 286 | 286 | } |
| 287 | - String uuid = UUID.randomUUID().toString(); | |
| 288 | - if (device == null) { | |
| 289 | - | |
| 290 | - resultHolder.put(key, key, result); | |
| 291 | - RequestMessage msg = new RequestMessage(); | |
| 292 | - msg.setKey(key); | |
| 293 | - msg.setId(uuid); | |
| 294 | - JSONObject json = new JSONObject(); | |
| 295 | - json.put("DeviceID", deviceId); | |
| 296 | - json.put("CmdType", "Broadcast"); | |
| 297 | - json.put("Result", "Failed"); | |
| 298 | - json.put("Description", "Device 不存在"); | |
| 299 | - msg.setData(json); | |
| 300 | - resultHolder.invokeResult(msg); | |
| 301 | - return result; | |
| 287 | + Device device = storager.queryVideoDevice(deviceId); | |
| 288 | + if (device == null) { | |
| 289 | + throw new ControllerException(ErrorCode.ERROR400.getCode(), "未找到设备: " + deviceId); | |
| 302 | 290 | } |
| 303 | - try { | |
| 304 | - cmder.audioBroadcastCmd(device, (event) -> { | |
| 305 | - RequestMessage msg = new RequestMessage(); | |
| 306 | - msg.setKey(key); | |
| 307 | - msg.setId(uuid); | |
| 308 | - JSONObject json = new JSONObject(); | |
| 309 | - json.put("DeviceID", deviceId); | |
| 310 | - json.put("CmdType", "Broadcast"); | |
| 311 | - json.put("Result", "Failed"); | |
| 312 | - json.put("Description", String.format("语音广播操作失败,错误码: %s, %s", event.statusCode, event.msg)); | |
| 313 | - msg.setData(json); | |
| 314 | - resultHolder.invokeResult(msg); | |
| 315 | - }); | |
| 316 | - } catch (InvalidArgumentException | SipException | ParseException e) { | |
| 317 | - logger.error("[命令发送失败] 语音广播: {}", e.getMessage()); | |
| 318 | - throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); | |
| 291 | + if (channelId == null) { | |
| 292 | + throw new ControllerException(ErrorCode.ERROR400.getCode(), "未找到通道: " + channelId); | |
| 319 | 293 | } |
| 320 | 294 | |
| 321 | - result.onTimeout(() -> { | |
| 322 | - logger.warn("语音广播操作超时, 设备未返回应答指令"); | |
| 323 | - RequestMessage msg = new RequestMessage(); | |
| 324 | - msg.setKey(key); | |
| 325 | - msg.setId(uuid); | |
| 326 | - JSONObject json = new JSONObject(); | |
| 327 | - json.put("DeviceID", deviceId); | |
| 328 | - json.put("CmdType", "Broadcast"); | |
| 329 | - json.put("Result", "Failed"); | |
| 330 | - json.put("Error", "Timeout. Device did not response to broadcast command."); | |
| 331 | - msg.setData(json); | |
| 332 | - resultHolder.invokeResult(msg); | |
| 333 | - }); | |
| 334 | - resultHolder.put(key, uuid, result); | |
| 335 | - return result; | |
| 295 | + return playService.audioBroadcast(device, channelId, broadcastMode); | |
| 296 | + | |
| 297 | + } | |
| 298 | + | |
| 299 | + @Operation(summary = "停止语音广播") | |
| 300 | + @Parameter(name = "deviceId", description = "设备Id", required = true) | |
| 301 | + @Parameter(name = "channelId", description = "通道Id", required = true) | |
| 302 | + @GetMapping("/broadcast/stop/{deviceId}/{channelId}") | |
| 303 | + @PostMapping("/broadcast/stop/{deviceId}/{channelId}") | |
| 304 | + public void stopBroadcast(@PathVariable String deviceId, @PathVariable String channelId) { | |
| 305 | + if (logger.isDebugEnabled()) { | |
| 306 | + logger.debug("停止语音广播API调用"); | |
| 307 | + } | |
| 308 | +// try { | |
| 309 | +// playService.stopAudioBroadcast(deviceId, channelId); | |
| 310 | +// } catch (InvalidArgumentException | ParseException | SipException e) { | |
| 311 | +// logger.error("[命令发送失败] 停止语音: {}", e.getMessage()); | |
| 312 | +// throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); | |
| 313 | +// } | |
| 314 | + playService.stopAudioBroadcast(deviceId, channelId); | |
| 336 | 315 | } |
| 337 | 316 | |
| 338 | 317 | @Operation(summary = "获取所有的ssrc", security = @SecurityRequirement(name = JwtUtils.HEADER)) | ... | ... |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/bean/AudioBroadcastEvent.java
0 → 100644
src/main/java/com/genersoft/iot/vmp/vmanager/ps/PsController.java
| ... | ... | @@ -102,7 +102,7 @@ public class PsController { |
| 102 | 102 | } |
| 103 | 103 | } |
| 104 | 104 | String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_PS_INFO + userSetting.getServerId() + "_" + callId + "_" + stream; |
| 105 | - int localPort = zlmServerFactory.createRTPServer(mediaServerItem, stream, ssrcInt, null, false, tcpMode); | |
| 105 | + int localPort = zlmServerFactory.createRTPServer(mediaServerItem, stream, ssrcInt, null, false, false, tcpMode); | |
| 106 | 106 | if (localPort == 0) { |
| 107 | 107 | throw new ControllerException(ErrorCode.ERROR100.getCode(), "获取端口失败"); |
| 108 | 108 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/vmanager/rtp/RtpController.java
| ... | ... | @@ -102,8 +102,8 @@ public class RtpController { |
| 102 | 102 | } |
| 103 | 103 | } |
| 104 | 104 | String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_" + callId + "_" + stream; |
| 105 | - int localPortForVideo = zlmServerFactory.createRTPServer(mediaServerItem, stream, ssrcInt, null, false, tcpMode); | |
| 106 | - int localPortForAudio = zlmServerFactory.createRTPServer(mediaServerItem, stream + "_a" , ssrcInt, null, false, tcpMode); | |
| 105 | + int localPortForVideo = zlmServerFactory.createRTPServer(mediaServerItem, stream, ssrcInt, null, false, false, tcpMode); | |
| 106 | + int localPortForAudio = zlmServerFactory.createRTPServer(mediaServerItem, stream + "_a" , ssrcInt, null, false, false, tcpMode); | |
| 107 | 107 | if (localPortForVideo == 0 || localPortForAudio == 0) { |
| 108 | 108 | throw new ControllerException(ErrorCode.ERROR100.getCode(), "获取端口失败"); |
| 109 | 109 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java
| ... | ... | @@ -25,6 +25,7 @@ import org.springframework.web.bind.annotation.*; |
| 25 | 25 | import javax.security.sasl.AuthenticationException; |
| 26 | 26 | import javax.servlet.http.HttpServletRequest; |
| 27 | 27 | import javax.servlet.http.HttpServletResponse; |
| 28 | +import java.time.LocalDateTime; | |
| 28 | 29 | import java.util.List; |
| 29 | 30 | |
| 30 | 31 | @Tag(name = "用户管理") |
| ... | ... | @@ -206,4 +207,17 @@ public class UserController { |
| 206 | 207 | } |
| 207 | 208 | } |
| 208 | 209 | } |
| 210 | + | |
| 211 | + @PostMapping("/userInfo") | |
| 212 | + @Operation(summary = "管理员修改普通用户密码") | |
| 213 | + public LoginUser getUserInfo() { | |
| 214 | + // 获取当前登录用户id | |
| 215 | + LoginUser userInfo = SecurityUtils.getUserInfo(); | |
| 216 | + | |
| 217 | + if (userInfo == null) { | |
| 218 | + throw new ControllerException(ErrorCode.ERROR100); | |
| 219 | + } | |
| 220 | + User user = userService.getUser(userInfo.getUsername(), userInfo.getPassword()); | |
| 221 | + return new LoginUser(user, LocalDateTime.now()); | |
| 222 | + } | |
| 209 | 223 | } | ... | ... |
src/main/resources/all-application.yml
| ... | ... | @@ -217,12 +217,16 @@ user-settings: |
| 217 | 217 | push-authority: true |
| 218 | 218 | # 设备上线时是否自动同步通道 |
| 219 | 219 | sync-channel-on-device-online: false |
| 220 | + # 国标级联语音喊话发流模式 * UDP:udp传输 TCP-ACTIVE:tcp主动模式 TCP-PASSIVE:tcp被动模式 | |
| 221 | + broadcast-for-platform: UDP | |
| 220 | 222 | # 是否使用设备来源Ip作为回复IP, 不设置则为 false |
| 221 | 223 | sip-use-source-ip-as-remote-address: false |
| 222 | 224 | # 是否开启sip日志 |
| 223 | 225 | sip-log: true |
| 224 | 226 | # 是否开启sql日志 |
| 225 | 227 | sql-log: true |
| 228 | + # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流 | |
| 229 | + push-stream-after-ack: false | |
| 226 | 230 | # 消息通道功能-缺少国标ID是否给所有上级发送消息 |
| 227 | 231 | send-to-platforms-when-id-lost: true |
| 228 | 232 | # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息 | ... | ... |
src/main/resources/local.jks
0 → 100644
No preview for this file type
web_src/config/index.js
| ... | ... | @@ -12,14 +12,14 @@ module.exports = { |
| 12 | 12 | assetsPublicPath: '/', |
| 13 | 13 | proxyTable: { |
| 14 | 14 | '/debug': { |
| 15 | - target: 'http://localhost:18080', | |
| 15 | + target: 'http://127.0.0.1:18082', | |
| 16 | 16 | changeOrigin: true, |
| 17 | 17 | pathRewrite: { |
| 18 | 18 | '^/debug': '/' |
| 19 | 19 | } |
| 20 | 20 | }, |
| 21 | 21 | '/static/snap': { |
| 22 | - target: 'http://localhost:18080', | |
| 22 | + target: 'http://127.0.0.1:18082', | |
| 23 | 23 | changeOrigin: true, |
| 24 | 24 | // pathRewrite: { |
| 25 | 25 | // '^/static/snap': '/static/snap' | ... | ... |
web_src/src/components/dialog/deviceEdit.vue
| ... | ... | @@ -43,6 +43,9 @@ |
| 43 | 43 | <el-option key="UTF-8" label="UTF-8" value="utf-8"></el-option> |
| 44 | 44 | </el-select> |
| 45 | 45 | </el-form-item> |
| 46 | + <el-form-item label="语音发送通道" prop="name"> | |
| 47 | + <el-input v-model="form.audioChannelForReceive" clearable></el-input> | |
| 48 | + </el-form-item> | |
| 46 | 49 | <el-form-item label="地理坐标系" prop="geoCoordSys" > |
| 47 | 50 | <el-select v-model="form.geoCoordSys" style="float: left; width: 100%" > |
| 48 | 51 | <el-option key="WGS84" label="WGS84" value="WGS84"></el-option> |
| ... | ... | @@ -61,6 +64,7 @@ |
| 61 | 64 | <el-form-item label="其他选项"> |
| 62 | 65 | <el-checkbox label="SSRC校验" v-model="form.ssrcCheck" style="float: left"></el-checkbox> |
| 63 | 66 | <el-checkbox label="作为消息通道" v-model="form.asMessageChannel" style="float: left"></el-checkbox> |
| 67 | + <el-checkbox label="收到ACK后发流" v-model="form.broadcastPushAfterAck" style="float: left"></el-checkbox> | |
| 64 | 68 | </el-form-item> |
| 65 | 69 | <el-form-item> |
| 66 | 70 | <div style="float: right;"> | ... | ... |
web_src/src/components/dialog/devicePlayer.vue
| 1 | 1 | <template> |
| 2 | -<div id="devicePlayer" v-loading="isLoging"> | |
| 2 | + <div id="devicePlayer" v-loading="isLoging"> | |
| 3 | 3 | |
| 4 | 4 | <el-dialog title="视频播放" top="0" :close-on-click-modal="false" :visible.sync="showVideoDialog" @close="close()" v-if="showVideoDialog"> |
| 5 | 5 | <div style="width: 100%; height: 100%"> |
| 6 | - <el-tabs type="card" :stretch="true" v-model="activePlayer" @tab-click="changePlayer" v-if="Object.keys(this.player).length > 1"> | |
| 7 | -<!-- <el-tab-pane label="LivePlayer" name="livePlayer">--> | |
| 8 | -<!-- <LivePlayer v-if="showVideoDialog" ref="livePlayer" :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" :hasaudio="hasAudio" fluent autoplay live></LivePlayer>--> | |
| 9 | -<!-- </el-tab-pane>--> | |
| 6 | + <el-tabs type="card" :stretch="true" v-model="activePlayer" @tab-click="changePlayer" | |
| 7 | + v-if="Object.keys(this.player).length > 1"> | |
| 10 | 8 | <el-tab-pane label="Jessibuca" name="jessibuca"> |
| 11 | - <jessibucaPlayer v-if="activePlayer === 'jessibuca'" ref="jessibuca" :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" height="100px" :hasAudio="hasAudio" fluent autoplay live ></jessibucaPlayer> | |
| 9 | + <jessibucaPlayer v-if="activePlayer === 'jessibuca'" ref="jessibuca" :visible.sync="showVideoDialog" | |
| 10 | + :videoUrl="videoUrl" :error="videoError" :message="videoError" height="100px" | |
| 11 | + :hasAudio="hasAudio" fluent autoplay live></jessibucaPlayer> | |
| 12 | 12 | </el-tab-pane> |
| 13 | 13 | <el-tab-pane label="WebRTC" name="webRTC"> |
| 14 | - <rtc-player v-if="activePlayer === 'webRTC'" ref="webRTC" :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" height="100px" :hasAudio="hasAudio" fluent autoplay live ></rtc-player> | |
| 14 | + <rtc-player v-if="activePlayer === 'webRTC'" ref="webRTC" :visible.sync="showVideoDialog" | |
| 15 | + :videoUrl="videoUrl" :error="videoError" :message="videoError" height="100px" | |
| 16 | + :hasAudio="hasAudio" fluent autoplay live></rtc-player> | |
| 15 | 17 | </el-tab-pane> |
| 16 | 18 | <el-tab-pane label="h265web">h265web敬请期待</el-tab-pane> |
| 17 | 19 | </el-tabs> |
| 18 | - <jessibucaPlayer v-if="Object.keys(this.player).length == 1 && this.player.jessibuca" ref="jessibuca" :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" height="100px" :hasAudio="hasAudio" fluent autoplay live ></jessibucaPlayer> | |
| 19 | - <rtc-player v-if="Object.keys(this.player).length == 1 && this.player.webRTC" ref="jessibuca" :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" height="100px" :hasAudio="hasAudio" fluent autoplay live ></rtc-player> | |
| 20 | + <jessibucaPlayer v-if="Object.keys(this.player).length == 1 && this.player.jessibuca" ref="jessibuca" | |
| 21 | + :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" | |
| 22 | + height="100px" :hasAudio="hasAudio" fluent autoplay live></jessibucaPlayer> | |
| 23 | + <rtc-player v-if="Object.keys(this.player).length == 1 && this.player.webRTC" ref="jessibuca" | |
| 24 | + :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" | |
| 25 | + height="100px" :hasAudio="hasAudio" fluent autoplay live></rtc-player> | |
| 20 | 26 | |
| 21 | 27 | </div> |
| 22 | - <div id="shared" style="text-align: right; margin-top: 1rem;"> | |
| 23 | - <el-tabs v-model="tabActiveName" @tab-click="tabHandleClick" > | |
| 24 | - <el-tab-pane label="实时视频" name="media"> | |
| 25 | - <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;"> | |
| 26 | - <span style="width: 5rem; line-height: 2.5rem; text-align: right;">播放地址:</span> | |
| 27 | - <el-input v-model="getPlayerShared.sharedUrl" :disabled="true" > | |
| 28 | - <template slot="append"> | |
| 29 | - <i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="getPlayerShared.sharedUrl" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i> | |
| 30 | - </template> | |
| 31 | - </el-input> | |
| 32 | - </div> | |
| 33 | - <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;"> | |
| 34 | - <span style="width: 5rem; line-height: 2.5rem; text-align: right;">iframe:</span> | |
| 35 | - <el-input v-model="getPlayerShared.sharedIframe" :disabled="true" > | |
| 36 | - <template slot="append"> | |
| 37 | - <i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="getPlayerShared.sharedIframe" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i> | |
| 38 | - </template> | |
| 39 | - </el-input> | |
| 40 | - </div> | |
| 41 | - <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;"> | |
| 42 | - <span style="width: 5rem; line-height: 2.5rem; text-align: right;">资源地址:</span> | |
| 43 | - <el-input v-model="getPlayerShared.sharedRtmp" :disabled="true" > | |
| 44 | - <el-button slot="append" icon="el-icon-document-copy" title="点击拷贝" v-clipboard="getPlayerShared.sharedRtmp" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button> | |
| 45 | - <el-dropdown slot="prepend" v-if="streamInfo" trigger="click" @command="copyUrl"> | |
| 46 | - <el-button > | |
| 47 | - 更多地址<i class="el-icon-arrow-down el-icon--right"></i> | |
| 48 | - </el-button> | |
| 49 | - <el-dropdown-menu slot="dropdown" > | |
| 50 | - <el-dropdown-item v-if="streamInfo.flv" :command="streamInfo.flv"> | |
| 51 | - <el-tag >FLV:</el-tag> | |
| 52 | - <span>{{ streamInfo.flv }}</span> | |
| 53 | - </el-dropdown-item> | |
| 54 | - <el-dropdown-item v-if="streamInfo.https_flv" :command="streamInfo.https_flv"> | |
| 55 | - <el-tag >FLV(https):</el-tag> | |
| 56 | - <span>{{ streamInfo.https_flv }}</span> | |
| 57 | - </el-dropdown-item> | |
| 58 | - <el-dropdown-item v-if="streamInfo.ws_flv" :command="streamInfo.ws_flv"> | |
| 59 | - <el-tag >FLV(ws):</el-tag> | |
| 60 | - <span >{{ streamInfo.ws_flv }}</span> | |
| 61 | - </el-dropdown-item> | |
| 62 | - <el-dropdown-item v-if="streamInfo.wss_flv" :command="streamInfo.wss_flv"> | |
| 63 | - <el-tag >FLV(wss):</el-tag> | |
| 64 | - <span>{{ streamInfo.wss_flv }}</span> | |
| 65 | - </el-dropdown-item> | |
| 66 | - <el-dropdown-item v-if="streamInfo.fmp4" :command="streamInfo.fmp4"> | |
| 67 | - <el-tag >FMP4:</el-tag> | |
| 68 | - <span>{{ streamInfo.fmp4 }}</span> | |
| 69 | - </el-dropdown-item> | |
| 70 | - <el-dropdown-item v-if="streamInfo.https_fmp4" :command="streamInfo.https_fmp4"> | |
| 71 | - <el-tag >FMP4(https):</el-tag> | |
| 72 | - <span>{{ streamInfo.https_fmp4 }}</span> | |
| 73 | - </el-dropdown-item> | |
| 74 | - <el-dropdown-item v-if="streamInfo.ws_fmp4" :command="streamInfo.ws_fmp4"> | |
| 75 | - <el-tag >FMP4(ws):</el-tag> | |
| 76 | - <span>{{ streamInfo.ws_fmp4 }}</span> | |
| 77 | - </el-dropdown-item> | |
| 78 | - <el-dropdown-item v-if="streamInfo.wss_fmp4" :command="streamInfo.wss_fmp4"> | |
| 79 | - <el-tag >FMP4(wss):</el-tag> | |
| 80 | - <span>{{ streamInfo.wss_fmp4 }}</span> | |
| 81 | - </el-dropdown-item> | |
| 82 | - <el-dropdown-item v-if="streamInfo.hls" :command="streamInfo.hls"> | |
| 83 | - <el-tag>HLS:</el-tag> | |
| 84 | - <span>{{ streamInfo.hls }}</span> | |
| 85 | - </el-dropdown-item> | |
| 86 | - <el-dropdown-item v-if="streamInfo.https_hls" :command="streamInfo.https_hls"> | |
| 87 | - <el-tag >HLS(https):</el-tag> | |
| 88 | - <span>{{ streamInfo.https_hls }}</span> | |
| 89 | - </el-dropdown-item> | |
| 90 | - <el-dropdown-item v-if="streamInfo.ws_hls" :command="streamInfo.ws_hls"> | |
| 91 | - <el-tag >HLS(ws):</el-tag> | |
| 92 | - <span>{{ streamInfo.ws_hls }}</span> | |
| 93 | - </el-dropdown-item> | |
| 94 | - <el-dropdown-item v-if="streamInfo.wss_hls" :command="streamInfo.wss_hls"> | |
| 95 | - <el-tag >HLS(wss):</el-tag> | |
| 96 | - <span>{{ streamInfo.wss_hls }}</span> | |
| 97 | - </el-dropdown-item> | |
| 98 | - <el-dropdown-item v-if="streamInfo.ts" :command="streamInfo.ts"> | |
| 99 | - <el-tag>TS:</el-tag> | |
| 100 | - <span>{{ streamInfo.ts }}</span> | |
| 101 | - </el-dropdown-item> | |
| 102 | - <el-dropdown-item v-if="streamInfo.https_ts" :command="streamInfo.https_ts"> | |
| 103 | - <el-tag>TS(https):</el-tag> | |
| 104 | - <span>{{ streamInfo.https_ts }}</span> | |
| 105 | - </el-dropdown-item> | |
| 106 | - <el-dropdown-item v-if="streamInfo.ws_ts" :command="streamInfo.ws_ts"> | |
| 107 | - <el-tag>TS(ws):</el-tag> | |
| 108 | - <span>{{ streamInfo.ws_ts }}</span> | |
| 109 | - </el-dropdown-item> | |
| 110 | - <el-dropdown-item v-if="streamInfo.wss_ts" :command="streamInfo.wss_ts"> | |
| 111 | - <el-tag>TS(wss):</el-tag> | |
| 112 | - <span>{{ streamInfo.wss_ts }}</span> | |
| 113 | - </el-dropdown-item> | |
| 114 | - <el-dropdown-item v-if="streamInfo.rtc" :command="streamInfo.rtc"> | |
| 115 | - <el-tag >RTC:</el-tag> | |
| 116 | - <span>{{ streamInfo.rtc }}</span> | |
| 117 | - </el-dropdown-item> | |
| 118 | - <el-dropdown-item v-if="streamInfo.rtcs" :command="streamInfo.rtcs"> | |
| 119 | - <el-tag >RTCS:</el-tag> | |
| 120 | - <span>{{ streamInfo.rtcs }}</span> | |
| 121 | - </el-dropdown-item> | |
| 122 | - <el-dropdown-item v-if="streamInfo.rtmp" :command="streamInfo.rtmp"> | |
| 123 | - <el-tag >RTMP:</el-tag> | |
| 124 | - <span>{{ streamInfo.rtmp }}</span> | |
| 125 | - </el-dropdown-item> | |
| 126 | - <el-dropdown-item v-if="streamInfo.rtmps" :command="streamInfo.rtmps"> | |
| 127 | - <el-tag >RTMPS:</el-tag> | |
| 128 | - <span>{{ streamInfo.rtmps }}</span> | |
| 129 | - </el-dropdown-item> | |
| 130 | - <el-dropdown-item v-if="streamInfo.rtsp" :command="streamInfo.rtsp"> | |
| 131 | - <el-tag >RTSP:</el-tag> | |
| 132 | - <span>{{ streamInfo.rtsp }}</span> | |
| 133 | - </el-dropdown-item> | |
| 134 | - <el-dropdown-item v-if="streamInfo.rtsps" :command="streamInfo.rtsps"> | |
| 135 | - <el-tag >RTSPS:</el-tag> | |
| 136 | - <span>{{ streamInfo.rtsps }}</span> | |
| 137 | - </el-dropdown-item> | |
| 138 | - </el-dropdown-menu> | |
| 139 | - </el-dropdown> | |
| 140 | - </el-input> | |
| 141 | - | |
| 142 | - </div> | |
| 143 | - </el-tab-pane> | |
| 144 | - <!--{"code":0,"data":{"paths":["22-29-30.mp4"],"rootPath":"/home/kkkkk/Documents/ZLMediaKit/release/linux/Debug/www/record/hls/kkkkk/2020-05-11/"}}--> | |
| 145 | - <!--遥控界面--> | |
| 146 | - <el-tab-pane label="云台控制" name="control" v-if="showPtz"> | |
| 147 | - <div style="display: flex; justify-content: left;"> | |
| 148 | - <div class="control-wrapper"> | |
| 149 | - <div class="control-btn control-top" @mousedown="ptzCamera('up')" @mouseup="ptzCamera('stop')"> | |
| 150 | - <i class="el-icon-caret-top"></i> | |
| 151 | - <div class="control-inner-btn control-inner"></div> | |
| 152 | - </div> | |
| 153 | - <div class="control-btn control-left" @mousedown="ptzCamera('left')" @mouseup="ptzCamera('stop')"> | |
| 154 | - <i class="el-icon-caret-left"></i> | |
| 155 | - <div class="control-inner-btn control-inner"></div> | |
| 156 | - </div> | |
| 157 | - <div class="control-btn control-bottom" @mousedown="ptzCamera('down')" @mouseup="ptzCamera('stop')"> | |
| 158 | - <i class="el-icon-caret-bottom"></i> | |
| 159 | - <div class="control-inner-btn control-inner"></div> | |
| 160 | - </div> | |
| 161 | - <div class="control-btn control-right" @mousedown="ptzCamera('right')" @mouseup="ptzCamera('stop')"> | |
| 162 | - <i class="el-icon-caret-right"></i> | |
| 163 | - <div class="control-inner-btn control-inner"></div> | |
| 164 | - </div> | |
| 165 | - <div class="control-round"> | |
| 166 | - <div class="control-round-inner"><i class="fa fa-pause-circle"></i></div> | |
| 167 | - </div> | |
| 168 | - <div style="position: absolute; left: 7.25rem; top: 1.25rem" @mousedown="ptzCamera('zoomin')" @mouseup="ptzCamera('stop')"><i class="el-icon-zoom-in control-zoom-btn" style="font-size: 1.875rem;"></i></div> | |
| 169 | - <div style="position: absolute; left: 7.25rem; top: 3.25rem; font-size: 1.875rem;" @mousedown="ptzCamera('zoomout')" @mouseup="ptzCamera('stop')"><i class="el-icon-zoom-out control-zoom-btn"></i></div> | |
| 170 | - <div class="contro-speed" style="position: absolute; left: 4px; top: 7rem; width: 9rem;"> | |
| 171 | - <el-slider v-model="controSpeed" :max="255"></el-slider> | |
| 172 | - </div> | |
| 173 | - </div> | |
| 174 | - | |
| 175 | - <div class="control-panel"> | |
| 176 | - <el-button-group> | |
| 177 | - <el-tag style="position :absolute; left: 0rem; top: 0rem; width: 5rem; text-align: center" size="medium">预置位编号</el-tag> | |
| 178 | - <el-input-number style="position: absolute; left: 5rem; top: 0rem; width: 6rem" size="mini" v-model="presetPos" controls-position="right" :precision="0" :step="1" :min="1" :max="255"></el-input-number> | |
| 179 | - <el-button style="position: absolute; left: 11rem; top: 0rem; width: 5rem" size="mini" icon="el-icon-add-location" @click="presetPosition(129, presetPos)">设置</el-button> | |
| 180 | - <el-button style="position: absolute; left: 27rem; top: 0rem; width: 5rem" size="mini" type="primary" icon="el-icon-place" @click="presetPosition(130, presetPos)">调用</el-button> | |
| 181 | - <el-button style="position: absolute; left: 16rem; top: 0rem; width: 5rem" size="mini" icon="el-icon-delete-location" @click="presetPosition(131, presetPos)">删除</el-button> | |
| 182 | - <el-tag style="position :absolute; left: 0rem; top: 2.5rem; width: 5rem; text-align: center" size="medium">巡航速度</el-tag> | |
| 183 | - <el-input-number style="position: absolute; left: 5rem; top: 2.5rem; width: 6rem" size="mini" v-model="cruisingSpeed" controls-position="right" :precision="0" :min="1" :max="4095"></el-input-number> | |
| 184 | - <el-button style="position: absolute; left: 11rem; top: 2.5rem; width: 5rem" size="mini" icon="el-icon-loading" @click="setSpeedOrTime(134, cruisingGroup, cruisingSpeed)">设置</el-button> | |
| 185 | - <el-tag style="position :absolute; left: 16rem; top: 2.5rem; width: 5rem; text-align: center" size="medium">停留时间</el-tag> | |
| 186 | - <el-input-number style="position: absolute; left: 21rem; top: 2.5rem; width: 6rem" size="mini" v-model="cruisingTime" controls-position="right" :precision="0" :min="1" :max="4095"></el-input-number> | |
| 187 | - <el-button style="position: absolute; left: 27rem; top: 2.5rem; width: 5rem" size="mini" icon="el-icon-timer" @click="setSpeedOrTime(135, cruisingGroup, cruisingTime)">设置</el-button> | |
| 188 | - <el-tag style="position :absolute; left: 0rem; top: 4.5rem; width: 5rem; text-align: center" size="medium">巡航组编号</el-tag> | |
| 189 | - <el-input-number style="position: absolute; left: 5rem; top: 4.5rem; width: 6rem" size="mini" v-model="cruisingGroup" controls-position="right" :precision="0" :min="0" :max="255"></el-input-number> | |
| 190 | - <el-button style="position: absolute; left: 11rem; top: 4.5rem; width: 5rem" size="mini" icon="el-icon-add-location" @click="setCommand(132, cruisingGroup, presetPos)">添加点</el-button> | |
| 191 | - <el-button style="position: absolute; left: 16rem; top: 4.5rem; width: 5rem" size="mini" icon="el-icon-delete-location" @click="setCommand(133, cruisingGroup, presetPos)">删除点</el-button> | |
| 192 | - <el-button style="position: absolute; left: 21rem; top: 4.5rem; width: 5rem" size="mini" icon="el-icon-delete" @click="setCommand(133, cruisingGroup, 0)">删除组</el-button> | |
| 193 | - <el-button style="position: absolute; left: 27rem; top: 5rem; width: 5rem" size="mini" type="primary" icon="el-icon-video-camera-solid" @click="setCommand(136, cruisingGroup, 0)">巡航</el-button> | |
| 194 | - <el-tag style="position :absolute; left: 0rem; top: 7rem; width: 5rem; text-align: center" size="medium">扫描速度</el-tag> | |
| 195 | - <el-input-number style="position: absolute; left: 5rem; top: 7rem; width: 6rem" size="mini" v-model="scanSpeed" controls-position="right" :precision="0" :min="1" :max="4095"></el-input-number> | |
| 196 | - <el-button style="position: absolute; left: 11rem; top: 7rem; width: 5rem" size="mini" icon="el-icon-loading" @click="setSpeedOrTime(138, scanGroup, scanSpeed)">设置</el-button> | |
| 197 | - <el-tag style="position :absolute; left: 0rem; top: 9rem; width: 5rem; text-align: center" size="medium">扫描组编号</el-tag> | |
| 198 | - <el-input-number style="position: absolute; left: 5rem; top: 9rem; width: 6rem" size="mini" v-model="scanGroup" controls-position="right" :precision="0" :step="1" :min="0" :max="255"></el-input-number> | |
| 199 | - <el-button style="position: absolute; left: 11rem; top: 9rem; width: 5rem" size="mini" icon="el-icon-d-arrow-left" @click="setCommand(137, scanGroup, 1)">左边界</el-button> | |
| 200 | - <el-button style="position: absolute; left: 16rem; top: 9rem; width: 5rem" size="mini" icon="el-icon-d-arrow-right" @click="setCommand(137, scanGroup, 2)">右边界</el-button> | |
| 201 | - <el-button style="position: absolute; left: 27rem; top: 7rem; width: 5rem" size="mini" type="primary" icon="el-icon-video-camera-solid" @click="setCommand(137, scanGroup, 0)">扫描</el-button> | |
| 202 | - <el-button style="position: absolute; left: 27rem; top: 9rem; width: 5rem" size="mini" type="danger" icon="el-icon-switch-button" @click="ptzCamera('stop')">停止</el-button> | |
| 203 | - </el-button-group> | |
| 204 | - </div> | |
| 205 | - </div> | |
| 206 | - </el-tab-pane> | |
| 207 | - <el-tab-pane label="编码信息" name="codec" v-loading="tracksLoading"> | |
| 208 | - <p> | |
| 209 | - 无法播放或者没有声音?   试一试  | |
| 210 | - <el-button size="mini" type="primary" v-if="!coverPlaying" @click="coverPlay">转码播放</el-button> | |
| 211 | - <el-button size="mini" type="danger" v-if="coverPlaying" @click="convertStopClick">停止转码</el-button> | |
| 212 | - </p> | |
| 213 | - <div class="trank" > | |
| 214 | - <p v-if="tracksNotLoaded" style="text-align: center;padding-top: 3rem;">暂无数据</p> | |
| 215 | - <div v-for="(item, index) in tracks" style="width: 50%; float: left" loading> | |
| 216 | - <span >流 {{index}}</span> | |
| 217 | - <div class="trankInfo" v-if="item.codec_type == 0"> | |
| 218 | - <p>格式: {{item.codec_id_name}}</p> | |
| 219 | - <p>类型: 视频</p> | |
| 220 | - <p>分辨率: {{item.width}} x {{item.height}}</p> | |
| 221 | - <p>帧率: {{item.fps}}</p> | |
| 222 | - </div> | |
| 223 | - <div class="trankInfo" v-if="item.codec_type == 1"> | |
| 224 | - <p>格式: {{item.codec_id_name}}</p> | |
| 225 | - <p>类型: 音频</p> | |
| 226 | - <p>采样位数: {{item.sample_bit}}</p> | |
| 227 | - <p>采样率: {{item.sample_rate}}</p> | |
| 228 | - </div> | |
| 229 | - </div> | |
| 230 | - | |
| 231 | - </div> | |
| 232 | - | |
| 233 | - </el-tab-pane> | |
| 234 | - | |
| 235 | - </el-tabs> | |
| 236 | - </div> | |
| 28 | + <div id="shared" style="text-align: right; margin-top: 1rem;"> | |
| 29 | + <el-tabs v-model="tabActiveName" @tab-click="tabHandleClick"> | |
| 30 | + <el-tab-pane label="实时视频" name="media"> | |
| 31 | + <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;"> | |
| 32 | + <span style="width: 5rem; line-height: 2.5rem; text-align: right;">播放地址:</span> | |
| 33 | + <el-input v-model="getPlayerShared.sharedUrl" :disabled="true"> | |
| 34 | + <template slot="append"> | |
| 35 | + <i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="getPlayerShared.sharedUrl" | |
| 36 | + @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i> | |
| 37 | + </template> | |
| 38 | + </el-input> | |
| 39 | + </div> | |
| 40 | + <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;"> | |
| 41 | + <span style="width: 5rem; line-height: 2.5rem; text-align: right;">iframe:</span> | |
| 42 | + <el-input v-model="getPlayerShared.sharedIframe" :disabled="true"> | |
| 43 | + <template slot="append"> | |
| 44 | + <i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="getPlayerShared.sharedIframe" | |
| 45 | + @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i> | |
| 46 | + </template> | |
| 47 | + </el-input> | |
| 48 | + </div> | |
| 49 | + <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;"> | |
| 50 | + <span style="width: 5rem; line-height: 2.5rem; text-align: right;">资源地址:</span> | |
| 51 | + <el-input v-model="getPlayerShared.sharedRtmp" :disabled="true"> | |
| 52 | + <el-button slot="append" icon="el-icon-document-copy" title="点击拷贝" | |
| 53 | + v-clipboard="getPlayerShared.sharedRtmp" | |
| 54 | + @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button> | |
| 55 | + <el-dropdown slot="prepend" v-if="streamInfo" trigger="click" @command="copyUrl"> | |
| 56 | + <el-button> | |
| 57 | + 更多地址<i class="el-icon-arrow-down el-icon--right"></i> | |
| 58 | + </el-button> | |
| 59 | + <el-dropdown-menu slot="dropdown"> | |
| 60 | + <el-dropdown-item v-if="streamInfo.flv" :command="streamInfo.flv"> | |
| 61 | + <el-tag>FLV:</el-tag> | |
| 62 | + <span>{{ streamInfo.flv }}</span> | |
| 63 | + </el-dropdown-item> | |
| 64 | + <el-dropdown-item v-if="streamInfo.https_flv" :command="streamInfo.https_flv"> | |
| 65 | + <el-tag>FLV(https):</el-tag> | |
| 66 | + <span>{{ streamInfo.https_flv }}</span> | |
| 67 | + </el-dropdown-item> | |
| 68 | + <el-dropdown-item v-if="streamInfo.ws_flv" :command="streamInfo.ws_flv"> | |
| 69 | + <el-tag>FLV(ws):</el-tag> | |
| 70 | + <span>{{ streamInfo.ws_flv }}</span> | |
| 71 | + </el-dropdown-item> | |
| 72 | + <el-dropdown-item v-if="streamInfo.wss_flv" :command="streamInfo.wss_flv"> | |
| 73 | + <el-tag>FLV(wss):</el-tag> | |
| 74 | + <span>{{ streamInfo.wss_flv }}</span> | |
| 75 | + </el-dropdown-item> | |
| 76 | + <el-dropdown-item v-if="streamInfo.fmp4" :command="streamInfo.fmp4"> | |
| 77 | + <el-tag>FMP4:</el-tag> | |
| 78 | + <span>{{ streamInfo.fmp4 }}</span> | |
| 79 | + </el-dropdown-item> | |
| 80 | + <el-dropdown-item v-if="streamInfo.https_fmp4" :command="streamInfo.https_fmp4"> | |
| 81 | + <el-tag>FMP4(https):</el-tag> | |
| 82 | + <span>{{ streamInfo.https_fmp4 }}</span> | |
| 83 | + </el-dropdown-item> | |
| 84 | + <el-dropdown-item v-if="streamInfo.ws_fmp4" :command="streamInfo.ws_fmp4"> | |
| 85 | + <el-tag>FMP4(ws):</el-tag> | |
| 86 | + <span>{{ streamInfo.ws_fmp4 }}</span> | |
| 87 | + </el-dropdown-item> | |
| 88 | + <el-dropdown-item v-if="streamInfo.wss_fmp4" :command="streamInfo.wss_fmp4"> | |
| 89 | + <el-tag>FMP4(wss):</el-tag> | |
| 90 | + <span>{{ streamInfo.wss_fmp4 }}</span> | |
| 91 | + </el-dropdown-item> | |
| 92 | + <el-dropdown-item v-if="streamInfo.hls" :command="streamInfo.hls"> | |
| 93 | + <el-tag>HLS:</el-tag> | |
| 94 | + <span>{{ streamInfo.hls }}</span> | |
| 95 | + </el-dropdown-item> | |
| 96 | + <el-dropdown-item v-if="streamInfo.https_hls" :command="streamInfo.https_hls"> | |
| 97 | + <el-tag>HLS(https):</el-tag> | |
| 98 | + <span>{{ streamInfo.https_hls }}</span> | |
| 99 | + </el-dropdown-item> | |
| 100 | + <el-dropdown-item v-if="streamInfo.ws_hls" :command="streamInfo.ws_hls"> | |
| 101 | + <el-tag>HLS(ws):</el-tag> | |
| 102 | + <span>{{ streamInfo.ws_hls }}</span> | |
| 103 | + </el-dropdown-item> | |
| 104 | + <el-dropdown-item v-if="streamInfo.wss_hls" :command="streamInfo.wss_hls"> | |
| 105 | + <el-tag>HLS(wss):</el-tag> | |
| 106 | + <span>{{ streamInfo.wss_hls }}</span> | |
| 107 | + </el-dropdown-item> | |
| 108 | + <el-dropdown-item v-if="streamInfo.ts" :command="streamInfo.ts"> | |
| 109 | + <el-tag>TS:</el-tag> | |
| 110 | + <span>{{ streamInfo.ts }}</span> | |
| 111 | + </el-dropdown-item> | |
| 112 | + <el-dropdown-item v-if="streamInfo.https_ts" :command="streamInfo.https_ts"> | |
| 113 | + <el-tag>TS(https):</el-tag> | |
| 114 | + <span>{{ streamInfo.https_ts }}</span> | |
| 115 | + </el-dropdown-item> | |
| 116 | + <el-dropdown-item v-if="streamInfo.ws_ts" :command="streamInfo.ws_ts"> | |
| 117 | + <el-tag>TS(ws):</el-tag> | |
| 118 | + <span>{{ streamInfo.ws_ts }}</span> | |
| 119 | + </el-dropdown-item> | |
| 120 | + <el-dropdown-item v-if="streamInfo.wss_ts" :command="streamInfo.wss_ts"> | |
| 121 | + <el-tag>TS(wss):</el-tag> | |
| 122 | + <span>{{ streamInfo.wss_ts }}</span> | |
| 123 | + </el-dropdown-item> | |
| 124 | + <el-dropdown-item v-if="streamInfo.rtc" :command="streamInfo.rtc"> | |
| 125 | + <el-tag>RTC:</el-tag> | |
| 126 | + <span>{{ streamInfo.rtc }}</span> | |
| 127 | + </el-dropdown-item> | |
| 128 | + <el-dropdown-item v-if="streamInfo.rtcs" :command="streamInfo.rtcs"> | |
| 129 | + <el-tag>RTCS:</el-tag> | |
| 130 | + <span>{{ streamInfo.rtcs }}</span> | |
| 131 | + </el-dropdown-item> | |
| 132 | + <el-dropdown-item v-if="streamInfo.rtmp" :command="streamInfo.rtmp"> | |
| 133 | + <el-tag>RTMP:</el-tag> | |
| 134 | + <span>{{ streamInfo.rtmp }}</span> | |
| 135 | + </el-dropdown-item> | |
| 136 | + <el-dropdown-item v-if="streamInfo.rtmps" :command="streamInfo.rtmps"> | |
| 137 | + <el-tag>RTMPS:</el-tag> | |
| 138 | + <span>{{ streamInfo.rtmps }}</span> | |
| 139 | + </el-dropdown-item> | |
| 140 | + <el-dropdown-item v-if="streamInfo.rtsp" :command="streamInfo.rtsp"> | |
| 141 | + <el-tag>RTSP:</el-tag> | |
| 142 | + <span>{{ streamInfo.rtsp }}</span> | |
| 143 | + </el-dropdown-item> | |
| 144 | + <el-dropdown-item v-if="streamInfo.rtsps" :command="streamInfo.rtsps"> | |
| 145 | + <el-tag>RTSPS:</el-tag> | |
| 146 | + <span>{{ streamInfo.rtsps }}</span> | |
| 147 | + </el-dropdown-item> | |
| 148 | + </el-dropdown-menu> | |
| 149 | + </el-dropdown> | |
| 150 | + </el-input> | |
| 151 | + | |
| 152 | + </div> | |
| 153 | + </el-tab-pane> | |
| 154 | + <!--{"code":0,"data":{"paths":["22-29-30.mp4"],"rootPath":"/home/kkkkk/Documents/ZLMediaKit/release/linux/Debug/www/record/hls/kkkkk/2020-05-11/"}}--> | |
| 155 | + <!--遥控界面--> | |
| 156 | + <el-tab-pane label="云台控制" name="control" v-if="showPtz"> | |
| 157 | + <div style="display: flex; justify-content: left;"> | |
| 158 | + <div class="control-wrapper"> | |
| 159 | + <div class="control-btn control-top" @mousedown="ptzCamera('up')" @mouseup="ptzCamera('stop')"> | |
| 160 | + <i class="el-icon-caret-top"></i> | |
| 161 | + <div class="control-inner-btn control-inner"></div> | |
| 162 | + </div> | |
| 163 | + <div class="control-btn control-left" @mousedown="ptzCamera('left')" @mouseup="ptzCamera('stop')"> | |
| 164 | + <i class="el-icon-caret-left"></i> | |
| 165 | + <div class="control-inner-btn control-inner"></div> | |
| 166 | + </div> | |
| 167 | + <div class="control-btn control-bottom" @mousedown="ptzCamera('down')" @mouseup="ptzCamera('stop')"> | |
| 168 | + <i class="el-icon-caret-bottom"></i> | |
| 169 | + <div class="control-inner-btn control-inner"></div> | |
| 170 | + </div> | |
| 171 | + <div class="control-btn control-right" @mousedown="ptzCamera('right')" @mouseup="ptzCamera('stop')"> | |
| 172 | + <i class="el-icon-caret-right"></i> | |
| 173 | + <div class="control-inner-btn control-inner"></div> | |
| 174 | + </div> | |
| 175 | + <div class="control-round"> | |
| 176 | + <div class="control-round-inner"><i class="fa fa-pause-circle"></i></div> | |
| 177 | + </div> | |
| 178 | + <div style="position: absolute; left: 7.25rem; top: 1.25rem" @mousedown="ptzCamera('zoomin')" | |
| 179 | + @mouseup="ptzCamera('stop')"><i class="el-icon-zoom-in control-zoom-btn" | |
| 180 | + style="font-size: 1.875rem;"></i></div> | |
| 181 | + <div style="position: absolute; left: 7.25rem; top: 3.25rem; font-size: 1.875rem;" | |
| 182 | + @mousedown="ptzCamera('zoomout')" @mouseup="ptzCamera('stop')"><i | |
| 183 | + class="el-icon-zoom-out control-zoom-btn"></i></div> | |
| 184 | + <div class="contro-speed" style="position: absolute; left: 4px; top: 7rem; width: 9rem;"> | |
| 185 | + <el-slider v-model="controSpeed" :max="255"></el-slider> | |
| 186 | + </div> | |
| 187 | + </div> | |
| 188 | + | |
| 189 | + <div class="control-panel"> | |
| 190 | + <el-button-group> | |
| 191 | + <el-tag style="position :absolute; left: 0rem; top: 0rem; width: 5rem; text-align: center" | |
| 192 | + size="medium">预置位编号 | |
| 193 | + </el-tag> | |
| 194 | + <el-input-number style="position: absolute; left: 5rem; top: 0rem; width: 6rem" size="mini" | |
| 195 | + v-model="presetPos" controls-position="right" :precision="0" :step="1" :min="1" | |
| 196 | + :max="255"></el-input-number> | |
| 197 | + <el-button style="position: absolute; left: 11rem; top: 0rem; width: 5rem" size="mini" | |
| 198 | + icon="el-icon-add-location" @click="presetPosition(129, presetPos)">设置 | |
| 199 | + </el-button> | |
| 200 | + <el-button style="position: absolute; left: 27rem; top: 0rem; width: 5rem" size="mini" type="primary" | |
| 201 | + icon="el-icon-place" @click="presetPosition(130, presetPos)">调用 | |
| 202 | + </el-button> | |
| 203 | + <el-button style="position: absolute; left: 16rem; top: 0rem; width: 5rem" size="mini" | |
| 204 | + icon="el-icon-delete-location" @click="presetPosition(131, presetPos)">删除 | |
| 205 | + </el-button> | |
| 206 | + <el-tag style="position :absolute; left: 0rem; top: 2.5rem; width: 5rem; text-align: center" | |
| 207 | + size="medium">巡航速度 | |
| 208 | + </el-tag> | |
| 209 | + <el-input-number style="position: absolute; left: 5rem; top: 2.5rem; width: 6rem" size="mini" | |
| 210 | + v-model="cruisingSpeed" controls-position="right" :precision="0" :min="1" | |
| 211 | + :max="4095"></el-input-number> | |
| 212 | + <el-button style="position: absolute; left: 11rem; top: 2.5rem; width: 5rem" size="mini" | |
| 213 | + icon="el-icon-loading" @click="setSpeedOrTime(134, cruisingGroup, cruisingSpeed)">设置 | |
| 214 | + </el-button> | |
| 215 | + <el-tag style="position :absolute; left: 16rem; top: 2.5rem; width: 5rem; text-align: center" | |
| 216 | + size="medium">停留时间 | |
| 217 | + </el-tag> | |
| 218 | + <el-input-number style="position: absolute; left: 21rem; top: 2.5rem; width: 6rem" size="mini" | |
| 219 | + v-model="cruisingTime" controls-position="right" :precision="0" :min="1" | |
| 220 | + :max="4095"></el-input-number> | |
| 221 | + <el-button style="position: absolute; left: 27rem; top: 2.5rem; width: 5rem" size="mini" | |
| 222 | + icon="el-icon-timer" @click="setSpeedOrTime(135, cruisingGroup, cruisingTime)">设置 | |
| 223 | + </el-button> | |
| 224 | + <el-tag style="position :absolute; left: 0rem; top: 4.5rem; width: 5rem; text-align: center" | |
| 225 | + size="medium">巡航组编号 | |
| 226 | + </el-tag> | |
| 227 | + <el-input-number style="position: absolute; left: 5rem; top: 4.5rem; width: 6rem" size="mini" | |
| 228 | + v-model="cruisingGroup" controls-position="right" :precision="0" :min="0" | |
| 229 | + :max="255"></el-input-number> | |
| 230 | + <el-button style="position: absolute; left: 11rem; top: 4.5rem; width: 5rem" size="mini" | |
| 231 | + icon="el-icon-add-location" @click="setCommand(132, cruisingGroup, presetPos)">添加点 | |
| 232 | + </el-button> | |
| 233 | + <el-button style="position: absolute; left: 16rem; top: 4.5rem; width: 5rem" size="mini" | |
| 234 | + icon="el-icon-delete-location" @click="setCommand(133, cruisingGroup, presetPos)">删除点 | |
| 235 | + </el-button> | |
| 236 | + <el-button style="position: absolute; left: 21rem; top: 4.5rem; width: 5rem" size="mini" | |
| 237 | + icon="el-icon-delete" @click="setCommand(133, cruisingGroup, 0)">删除组 | |
| 238 | + </el-button> | |
| 239 | + <el-button style="position: absolute; left: 27rem; top: 5rem; width: 5rem" size="mini" type="primary" | |
| 240 | + icon="el-icon-video-camera-solid" @click="setCommand(136, cruisingGroup, 0)">巡航 | |
| 241 | + </el-button> | |
| 242 | + <el-tag style="position :absolute; left: 0rem; top: 7rem; width: 5rem; text-align: center" | |
| 243 | + size="medium">扫描速度 | |
| 244 | + </el-tag> | |
| 245 | + <el-input-number style="position: absolute; left: 5rem; top: 7rem; width: 6rem" size="mini" | |
| 246 | + v-model="scanSpeed" controls-position="right" :precision="0" :min="1" | |
| 247 | + :max="4095"></el-input-number> | |
| 248 | + <el-button style="position: absolute; left: 11rem; top: 7rem; width: 5rem" size="mini" | |
| 249 | + icon="el-icon-loading" @click="setSpeedOrTime(138, scanGroup, scanSpeed)">设置 | |
| 250 | + </el-button> | |
| 251 | + <el-tag style="position :absolute; left: 0rem; top: 9rem; width: 5rem; text-align: center" | |
| 252 | + size="medium">扫描组编号 | |
| 253 | + </el-tag> | |
| 254 | + <el-input-number style="position: absolute; left: 5rem; top: 9rem; width: 6rem" size="mini" | |
| 255 | + v-model="scanGroup" controls-position="right" :precision="0" :step="1" :min="0" | |
| 256 | + :max="255"></el-input-number> | |
| 257 | + <el-button style="position: absolute; left: 11rem; top: 9rem; width: 5rem" size="mini" | |
| 258 | + icon="el-icon-d-arrow-left" @click="setCommand(137, scanGroup, 1)">左边界 | |
| 259 | + </el-button> | |
| 260 | + <el-button style="position: absolute; left: 16rem; top: 9rem; width: 5rem" size="mini" | |
| 261 | + icon="el-icon-d-arrow-right" @click="setCommand(137, scanGroup, 2)">右边界 | |
| 262 | + </el-button> | |
| 263 | + <el-button style="position: absolute; left: 27rem; top: 7rem; width: 5rem" size="mini" type="primary" | |
| 264 | + icon="el-icon-video-camera-solid" @click="setCommand(137, scanGroup, 0)">扫描 | |
| 265 | + </el-button> | |
| 266 | + <el-button style="position: absolute; left: 27rem; top: 9rem; width: 5rem" size="mini" type="danger" | |
| 267 | + icon="el-icon-switch-button" @click="ptzCamera('stop')">停止 | |
| 268 | + </el-button> | |
| 269 | + </el-button-group> | |
| 270 | + </div> | |
| 271 | + </div> | |
| 272 | + </el-tab-pane> | |
| 273 | + <el-tab-pane label="编码信息" name="codec" v-loading="tracksLoading"> | |
| 274 | + <p> | |
| 275 | + 无法播放或者没有声音?   试一试  | |
| 276 | + <el-button size="mini" type="primary" v-if="!coverPlaying" @click="coverPlay">转码播放</el-button> | |
| 277 | + <el-button size="mini" type="danger" v-if="coverPlaying" @click="convertStopClick">停止转码</el-button> | |
| 278 | + </p> | |
| 279 | + <div class="trank"> | |
| 280 | + <p v-if="tracksNotLoaded" style="text-align: center;padding-top: 3rem;">暂无数据</p> | |
| 281 | + <div v-for="(item, index) in tracks" style="width: 50%; float: left" loading> | |
| 282 | + <span>流 {{ index }}</span> | |
| 283 | + <div class="trankInfo" v-if="item.codec_type == 0"> | |
| 284 | + <p>格式: {{ item.codec_id_name }}</p> | |
| 285 | + <p>类型: 视频</p> | |
| 286 | + <p>分辨率: {{ item.width }} x {{ item.height }}</p> | |
| 287 | + <p>帧率: {{ item.fps }}</p> | |
| 288 | + </div> | |
| 289 | + <div class="trankInfo" v-if="item.codec_type == 1"> | |
| 290 | + <p>格式: {{ item.codec_id_name }}</p> | |
| 291 | + <p>类型: 音频</p> | |
| 292 | + <p>采样位数: {{ item.sample_bit }}</p> | |
| 293 | + <p>采样率: {{ item.sample_rate }}</p> | |
| 294 | + </div> | |
| 295 | + </div> | |
| 296 | + | |
| 297 | + </div> | |
| 298 | + | |
| 299 | + </el-tab-pane> | |
| 300 | + <el-tab-pane label="语音对讲" name="broadcast"> | |
| 301 | + <div style="padding: 0 10px"> | |
| 302 | + <el-switch v-model="broadcastMode" :disabled="broadcastStatus !== -1" active-color="#409EFF" | |
| 303 | + active-text="喊话(Broadcast)" | |
| 304 | + inactive-text="对讲(Talk)"></el-switch> | |
| 305 | + </div> | |
| 306 | + <div class="trank" style="text-align: center;"> | |
| 307 | + <el-button @click="broadcastStatusClick()" :type="getBroadcastStatus()" :disabled="broadcastStatus === -2" | |
| 308 | + circle icon="el-icon-microphone" style="font-size: 32px; padding: 24px;margin-top: 24px;"/> | |
| 309 | + <p> | |
| 310 | + <span v-if="broadcastStatus === -2">正在释放资源</span> | |
| 311 | + <span v-if="broadcastStatus === -1">点击开始对讲</span> | |
| 312 | + <span v-if="broadcastStatus === 0">等待接通中...</span> | |
| 313 | + <span v-if="broadcastStatus === 1">请说话</span> | |
| 314 | + </p> | |
| 315 | + | |
| 316 | + </div> | |
| 317 | + </el-tab-pane> | |
| 318 | + | |
| 319 | + </el-tabs> | |
| 320 | + </div> | |
| 237 | 321 | </el-dialog> |
| 238 | -</div> | |
| 322 | + </div> | |
| 239 | 323 | </template> |
| 240 | 324 | |
| 241 | 325 | <script> |
| 242 | 326 | import rtcPlayer from '../dialog/rtcPlayer.vue' |
| 243 | 327 | import LivePlayer from '@liveqing/liveplayer' |
| 328 | +import crypto from 'crypto' | |
| 244 | 329 | import jessibucaPlayer from '../common/jessibuca.vue' |
| 330 | + | |
| 245 | 331 | export default { |
| 246 | - name: 'devicePlayer', | |
| 247 | - props: {}, | |
| 248 | - components: { | |
| 249 | - LivePlayer, jessibucaPlayer, rtcPlayer, | |
| 332 | + name: 'devicePlayer', | |
| 333 | + props: {}, | |
| 334 | + components: { | |
| 335 | + LivePlayer, jessibucaPlayer, rtcPlayer, | |
| 336 | + }, | |
| 337 | + computed: { | |
| 338 | + getPlayerShared: function () { | |
| 339 | + return { | |
| 340 | + sharedUrl: window.location.origin + '/#/play/wasm/' + encodeURIComponent(this.videoUrl), | |
| 341 | + sharedIframe: '<iframe src="' + window.location.origin + '/#/play/wasm/' + encodeURIComponent(this.videoUrl) + '"></iframe>', | |
| 342 | + sharedRtmp: this.videoUrl | |
| 343 | + }; | |
| 344 | + } | |
| 345 | + }, | |
| 346 | + created() { | |
| 347 | + console.log("created") | |
| 348 | + console.log(this.player) | |
| 349 | + this.broadcastStatus = -1; | |
| 350 | + if (Object.keys(this.player).length === 1) { | |
| 351 | + this.activePlayer = Object.keys(this.player)[0] | |
| 352 | + } | |
| 353 | + }, | |
| 354 | + data() { | |
| 355 | + return { | |
| 356 | + video: 'http://lndxyj.iqilu.com/public/upload/2019/10/14/8c001ea0c09cdc59a57829dabc8010fa.mp4', | |
| 357 | + videoUrl: '', | |
| 358 | + activePlayer: "jessibuca", | |
| 359 | + // 如何你只是用一种播放器,直接注释掉不用的部分即可 | |
| 360 | + player: { | |
| 361 | + jessibuca: ["ws_flv", "wss_flv"], | |
| 362 | + webRTC: ["rtc", "rtcs"], | |
| 363 | + }, | |
| 364 | + showVideoDialog: false, | |
| 365 | + streamId: '', | |
| 366 | + app: '', | |
| 367 | + mediaServerId: '', | |
| 368 | + convertKey: '', | |
| 369 | + deviceId: '', | |
| 370 | + channelId: '', | |
| 371 | + tabActiveName: 'media', | |
| 372 | + hasAudio: false, | |
| 373 | + loadingRecords: false, | |
| 374 | + recordsLoading: false, | |
| 375 | + isLoging: false, | |
| 376 | + controSpeed: 30, | |
| 377 | + timeVal: 0, | |
| 378 | + timeMin: 0, | |
| 379 | + timeMax: 1440, | |
| 380 | + presetPos: 1, | |
| 381 | + cruisingSpeed: 100, | |
| 382 | + cruisingTime: 5, | |
| 383 | + cruisingGroup: 0, | |
| 384 | + scanSpeed: 100, | |
| 385 | + scanGroup: 0, | |
| 386 | + tracks: [], | |
| 387 | + coverPlaying: false, | |
| 388 | + tracksLoading: false, | |
| 389 | + showPtz: true, | |
| 390 | + showRrecord: true, | |
| 391 | + tracksNotLoaded: false, | |
| 392 | + sliderTime: 0, | |
| 393 | + seekTime: 0, | |
| 394 | + recordStartTime: 0, | |
| 395 | + showTimeText: "00:00:00", | |
| 396 | + streamInfo: null, | |
| 397 | + broadcastMode: true, | |
| 398 | + broadcastRtc: null, | |
| 399 | + broadcastStatus: -1, // -2 正在释放资源 -1 默认状态 0 等待接通 1 接通成功 | |
| 400 | + }; | |
| 401 | + }, | |
| 402 | + methods: { | |
| 403 | + tabHandleClick: function (tab, event) { | |
| 404 | + console.log(tab) | |
| 405 | + var that = this; | |
| 406 | + that.tracks = []; | |
| 407 | + that.tracksLoading = true; | |
| 408 | + that.tracksNotLoaded = false; | |
| 409 | + if (tab.name === "codec") { | |
| 410 | + this.$axios({ | |
| 411 | + method: 'get', | |
| 412 | + url: '/zlm/' + this.mediaServerId + '/index/api/getMediaInfo?vhost=__defaultVhost__&schema=rtsp&app=' + this.app + '&stream=' + this.streamId | |
| 413 | + }).then(function (res) { | |
| 414 | + that.tracksLoading = false; | |
| 415 | + if (res.data.code == 0 && res.data.tracks) { | |
| 416 | + that.tracks = res.data.tracks; | |
| 417 | + } else { | |
| 418 | + that.tracksNotLoaded = true; | |
| 419 | + that.$message({ | |
| 420 | + showClose: true, | |
| 421 | + message: '获取编码信息失败,', | |
| 422 | + type: 'warning' | |
| 423 | + }); | |
| 424 | + } | |
| 425 | + }).catch(function (e) { | |
| 426 | + }); | |
| 427 | + } | |
| 250 | 428 | }, |
| 251 | - computed: { | |
| 252 | - getPlayerShared: function () { | |
| 253 | - return { | |
| 254 | - sharedUrl: window.location.origin + '/#/play/wasm/' + encodeURIComponent(this.videoUrl), | |
| 255 | - sharedIframe: '<iframe src="' + window.location.origin + '/#/play/wasm/' + encodeURIComponent(this.videoUrl) + '"></iframe>', | |
| 256 | - sharedRtmp: this.videoUrl | |
| 257 | - }; | |
| 258 | - } | |
| 429 | + changePlayer: function (tab) { | |
| 430 | + console.log(this.player[tab.name][0]) | |
| 431 | + this.activePlayer = tab.name; | |
| 432 | + this.videoUrl = this.getUrlByStreamInfo() | |
| 433 | + console.log(this.videoUrl) | |
| 259 | 434 | }, |
| 260 | - created() { | |
| 261 | - console.log(this.player) | |
| 262 | - if (Object.keys(this.player).length === 1) { | |
| 263 | - this.activePlayer = Object.keys(this.player)[0] | |
| 435 | + openDialog: function (tab, deviceId, channelId, param) { | |
| 436 | + if (this.showVideoDialog) { | |
| 437 | + return; | |
| 438 | + } | |
| 439 | + this.tabActiveName = tab; | |
| 440 | + this.channelId = channelId; | |
| 441 | + this.deviceId = deviceId; | |
| 442 | + this.streamId = ""; | |
| 443 | + this.mediaServerId = ""; | |
| 444 | + this.app = ""; | |
| 445 | + this.videoUrl = "" | |
| 446 | + if (!!this.$refs[this.activePlayer]) { | |
| 447 | + this.$refs[this.activePlayer].pause(); | |
| 448 | + } | |
| 449 | + switch (tab) { | |
| 450 | + case "media": | |
| 451 | + this.play(param.streamInfo, param.hasAudio) | |
| 452 | + break; | |
| 453 | + case "streamPlay": | |
| 454 | + this.tabActiveName = "media"; | |
| 455 | + this.showRrecord = false; | |
| 456 | + this.showPtz = false; | |
| 457 | + this.play(param.streamInfo, param.hasAudio) | |
| 458 | + break; | |
| 459 | + case "control": | |
| 460 | + break; | |
| 264 | 461 | } |
| 265 | 462 | }, |
| 266 | - data() { | |
| 267 | - return { | |
| 268 | - video: 'http://lndxyj.iqilu.com/public/upload/2019/10/14/8c001ea0c09cdc59a57829dabc8010fa.mp4', | |
| 269 | - videoUrl: '', | |
| 270 | - activePlayer: "jessibuca", | |
| 271 | - // 如何你只是用一种播放器,直接注释掉不用的部分即可 | |
| 272 | - player: { | |
| 273 | - jessibuca : ["ws_flv", "wss_flv"], | |
| 274 | - livePlayer : ["ws_flv", "wss_flv"], | |
| 275 | - webRTC: ["rtc", "rtcs"], | |
| 276 | - }, | |
| 277 | - showVideoDialog: false, | |
| 278 | - streamId: '', | |
| 279 | - app : '', | |
| 280 | - mediaServerId : '', | |
| 281 | - convertKey: '', | |
| 282 | - deviceId: '', | |
| 283 | - channelId: '', | |
| 284 | - tabActiveName: 'media', | |
| 285 | - hasAudio: false, | |
| 286 | - loadingRecords: false, | |
| 287 | - recordsLoading: false, | |
| 288 | - isLoging: false, | |
| 289 | - controSpeed: 30, | |
| 290 | - timeVal: 0, | |
| 291 | - timeMin: 0, | |
| 292 | - timeMax: 1440, | |
| 293 | - presetPos: 1, | |
| 294 | - cruisingSpeed: 100, | |
| 295 | - cruisingTime: 5, | |
| 296 | - cruisingGroup: 0, | |
| 297 | - scanSpeed: 100, | |
| 298 | - scanGroup: 0, | |
| 299 | - tracks: [], | |
| 300 | - coverPlaying:false, | |
| 301 | - tracksLoading: false, | |
| 302 | - showPtz: true, | |
| 303 | - showRrecord: true, | |
| 304 | - tracksNotLoaded: false, | |
| 305 | - sliderTime: 0, | |
| 306 | - seekTime: 0, | |
| 307 | - recordStartTime: 0, | |
| 308 | - showTimeText: "00:00:00", | |
| 309 | - streamInfo: null, | |
| 310 | - }; | |
| 463 | + play: function (streamInfo, hasAudio) { | |
| 464 | + this.streamInfo = streamInfo; | |
| 465 | + this.hasAudio = hasAudio; | |
| 466 | + this.isLoging = false; | |
| 467 | + // this.videoUrl = streamInfo.rtc; | |
| 468 | + this.videoUrl = this.getUrlByStreamInfo(); | |
| 469 | + this.streamId = streamInfo.stream; | |
| 470 | + this.app = streamInfo.app; | |
| 471 | + this.mediaServerId = streamInfo.mediaServerId; | |
| 472 | + this.playFromStreamInfo(false, streamInfo) | |
| 311 | 473 | }, |
| 312 | - methods: { | |
| 313 | - tabHandleClick: function(tab, event) { | |
| 314 | - console.log(tab) | |
| 315 | - var that = this; | |
| 316 | - that.tracks = []; | |
| 317 | - that.tracksLoading = true; | |
| 318 | - that.tracksNotLoaded = false; | |
| 319 | - if (tab.name === "codec") { | |
| 320 | - this.$axios({ | |
| 321 | - method: 'get', | |
| 322 | - url: '/zlm/' +this.mediaServerId+ '/index/api/getMediaInfo?vhost=__defaultVhost__&schema=rtsp&app='+ this.app +'&stream='+ this.streamId | |
| 323 | - }).then(function (res) { | |
| 324 | - that.tracksLoading = false; | |
| 325 | - if (res.data.code == 0 && res.data.tracks) { | |
| 326 | - that.tracks = res.data.tracks; | |
| 327 | - }else{ | |
| 328 | - that.tracksNotLoaded = true; | |
| 329 | - that.$message({ | |
| 330 | - showClose: true, | |
| 331 | - message: '获取编码信息失败,', | |
| 332 | - type: 'warning' | |
| 333 | - }); | |
| 334 | - } | |
| 335 | - }).catch(function (e) {}); | |
| 336 | - } | |
| 337 | - }, | |
| 338 | - changePlayer: function (tab) { | |
| 339 | - console.log(this.player[tab.name][0]) | |
| 340 | - this.activePlayer = tab.name; | |
| 341 | - this.videoUrl = this.getUrlByStreamInfo() | |
| 342 | - console.log(this.videoUrl) | |
| 343 | - }, | |
| 344 | - openDialog: function (tab, deviceId, channelId, param) { | |
| 345 | - if (this.showVideoDialog) { | |
| 346 | - return; | |
| 347 | - } | |
| 348 | - this.tabActiveName = tab; | |
| 349 | - this.channelId = channelId; | |
| 350 | - this.deviceId = deviceId; | |
| 351 | - this.streamId = ""; | |
| 352 | - this.mediaServerId = ""; | |
| 353 | - this.app = ""; | |
| 354 | - this.videoUrl = "" | |
| 355 | - if (!!this.$refs[this.activePlayer]) { | |
| 356 | - this.$refs[this.activePlayer].pause(); | |
| 357 | - } | |
| 358 | - switch (tab) { | |
| 359 | - case "media": | |
| 360 | - this.play(param.streamInfo, param.hasAudio) | |
| 361 | - break; | |
| 362 | - case "streamPlay": | |
| 363 | - this.tabActiveName = "media"; | |
| 364 | - this.showRrecord = false; | |
| 365 | - this.showPtz = false; | |
| 366 | - this.play(param.streamInfo, param.hasAudio) | |
| 367 | - break; | |
| 368 | - case "control": | |
| 369 | - break; | |
| 370 | - } | |
| 371 | - }, | |
| 372 | - play: function (streamInfo, hasAudio) { | |
| 373 | - this.streamInfo = streamInfo; | |
| 374 | - this.hasAudio = hasAudio; | |
| 375 | - this.isLoging = false; | |
| 376 | - // this.videoUrl = streamInfo.rtc; | |
| 377 | - this.videoUrl = this.getUrlByStreamInfo(); | |
| 378 | - this.streamId = streamInfo.stream; | |
| 379 | - this.app = streamInfo.app; | |
| 380 | - this.mediaServerId = streamInfo.mediaServerId; | |
| 381 | - this.playFromStreamInfo(false, streamInfo) | |
| 382 | - }, | |
| 383 | - getUrlByStreamInfo(){ | |
| 384 | - console.log(this.streamInfo) | |
| 385 | - if (location.protocol === "https:") { | |
| 386 | - this.videoUrl = this.streamInfo[this.player[this.activePlayer][1]] | |
| 387 | - }else { | |
| 388 | - this.videoUrl = this.streamInfo[this.player[this.activePlayer][0]] | |
| 389 | - } | |
| 390 | - return this.videoUrl; | |
| 474 | + getUrlByStreamInfo() { | |
| 475 | + console.log(this.streamInfo) | |
| 476 | + if (location.protocol === "https:") { | |
| 477 | + this.videoUrl = this.streamInfo[this.player[this.activePlayer][1]] | |
| 478 | + } else { | |
| 479 | + this.videoUrl = this.streamInfo[this.player[this.activePlayer][0]] | |
| 480 | + } | |
| 481 | + return this.videoUrl; | |
| 391 | 482 | |
| 392 | - }, | |
| 393 | - coverPlay: function () { | |
| 394 | - var that = this; | |
| 395 | - this.coverPlaying = true; | |
| 396 | - this.$refs[this.activePlayer].pause() | |
| 397 | - that.$axios({ | |
| 398 | - method: 'post', | |
| 399 | - url: '/api/play/convert/' + that.streamId | |
| 400 | - }).then(function (res) { | |
| 401 | - if (res.data.code === 0) { | |
| 402 | - that.convertKey = res.data.key; | |
| 403 | - setTimeout(()=>{ | |
| 404 | - that.isLoging = false; | |
| 405 | - that.playFromStreamInfo(false, res.data.data); | |
| 406 | - }, 2000) | |
| 407 | - } else { | |
| 408 | - that.isLoging = false; | |
| 409 | - that.coverPlaying = false; | |
| 410 | - that.$message({ | |
| 411 | - showClose: true, | |
| 412 | - message: '转码失败', | |
| 413 | - type: 'error' | |
| 414 | - }); | |
| 415 | - } | |
| 416 | - }).catch(function (e) { | |
| 417 | - console.log(e) | |
| 418 | - that.coverPlaying = false; | |
| 419 | - that.$message({ | |
| 420 | - showClose: true, | |
| 421 | - message: '播放错误', | |
| 422 | - type: 'error' | |
| 423 | - }); | |
| 424 | - }); | |
| 425 | - }, | |
| 426 | - convertStopClick: function() { | |
| 427 | - this.convertStop(()=>{ | |
| 428 | - this.$refs[this.activePlayer].play(this.videoUrl) | |
| 429 | - }); | |
| 430 | - }, | |
| 431 | - convertStop: function(callback) { | |
| 432 | - var that = this; | |
| 433 | - that.$refs.videoPlayer.pause() | |
| 434 | - this.$axios({ | |
| 435 | - method: 'post', | |
| 436 | - url: '/api/play/convertStop/' + this.convertKey | |
| 437 | - }).then(function (res) { | |
| 438 | - if (res.data.code == 0) { | |
| 439 | - console.log(res.data.msg) | |
| 440 | - }else { | |
| 441 | - console.error(res.data.msg) | |
| 442 | - } | |
| 443 | - if (callback )callback(); | |
| 444 | - }).catch(function (e) {}); | |
| 445 | - that.coverPlaying = false; | |
| 446 | - that.convertKey = ""; | |
| 447 | - // if (callback )callback(); | |
| 448 | - }, | |
| 483 | + }, | |
| 484 | + coverPlay: function () { | |
| 485 | + var that = this; | |
| 486 | + this.coverPlaying = true; | |
| 487 | + this.$refs[this.activePlayer].pause() | |
| 488 | + that.$axios({ | |
| 489 | + method: 'post', | |
| 490 | + url: '/api/play/convert/' + that.streamId | |
| 491 | + }).then(function (res) { | |
| 492 | + if (res.data.code === 0) { | |
| 493 | + that.convertKey = res.data.key; | |
| 494 | + setTimeout(() => { | |
| 495 | + that.isLoging = false; | |
| 496 | + that.playFromStreamInfo(false, res.data.data); | |
| 497 | + }, 2000) | |
| 498 | + } else { | |
| 499 | + that.isLoging = false; | |
| 500 | + that.coverPlaying = false; | |
| 501 | + that.$message({ | |
| 502 | + showClose: true, | |
| 503 | + message: '转码失败', | |
| 504 | + type: 'error' | |
| 505 | + }); | |
| 506 | + } | |
| 507 | + }).catch(function (e) { | |
| 508 | + console.log(e) | |
| 509 | + that.coverPlaying = false; | |
| 510 | + that.$message({ | |
| 511 | + showClose: true, | |
| 512 | + message: '播放错误', | |
| 513 | + type: 'error' | |
| 514 | + }); | |
| 515 | + }); | |
| 516 | + }, | |
| 517 | + convertStopClick: function () { | |
| 518 | + this.convertStop(() => { | |
| 519 | + this.$refs[this.activePlayer].play(this.videoUrl) | |
| 520 | + }); | |
| 521 | + }, | |
| 522 | + convertStop: function (callback) { | |
| 523 | + var that = this; | |
| 524 | + that.$refs.videoPlayer.pause() | |
| 525 | + this.$axios({ | |
| 526 | + method: 'post', | |
| 527 | + url: '/api/play/convertStop/' + this.convertKey | |
| 528 | + }).then(function (res) { | |
| 529 | + if (res.data.code == 0) { | |
| 530 | + console.log(res.data.msg) | |
| 531 | + } else { | |
| 532 | + console.error(res.data.msg) | |
| 533 | + } | |
| 534 | + if (callback) callback(); | |
| 535 | + }).catch(function (e) { | |
| 536 | + }); | |
| 537 | + that.coverPlaying = false; | |
| 538 | + that.convertKey = ""; | |
| 539 | + // if (callback )callback(); | |
| 540 | + }, | |
| 449 | 541 | |
| 450 | 542 | playFromStreamInfo: function (realHasAudio, streamInfo) { |
| 451 | 543 | this.showVideoDialog = true; |
| ... | ... | @@ -457,8 +549,6 @@ export default { |
| 457 | 549 | this.$refs[this.activePlayer].play(this.getUrlByStreamInfo(streamInfo)) |
| 458 | 550 | }); |
| 459 | 551 | } |
| 460 | - | |
| 461 | - | |
| 462 | 552 | }, |
| 463 | 553 | close: function () { |
| 464 | 554 | console.log('关闭视频'); |
| ... | ... | @@ -472,267 +562,436 @@ export default { |
| 472 | 562 | this.convertStop(); |
| 473 | 563 | } |
| 474 | 564 | this.convertKey = '' |
| 565 | + this.stopBroadcast() | |
| 475 | 566 | }, |
| 476 | 567 | |
| 477 | - copySharedInfo: function (data) { | |
| 478 | - console.log('复制内容:' + data); | |
| 479 | - this.coverPlaying = false; | |
| 480 | - this.tracks = [] | |
| 481 | - let _this = this; | |
| 482 | - this.$copyText(data).then( | |
| 483 | - function (e) { | |
| 484 | - _this.$message({ | |
| 485 | - showClose: true, | |
| 486 | - message: '复制成功', | |
| 487 | - type: 'success' | |
| 488 | - }); | |
| 489 | - }, | |
| 490 | - function (e) { | |
| 491 | - _this.$message({ | |
| 492 | - showClose: true, | |
| 493 | - message: '复制失败,请手动复制', | |
| 494 | - type: 'error' | |
| 495 | - }); | |
| 496 | - } | |
| 497 | - ); | |
| 498 | - }, | |
| 499 | - ptzCamera: function (command) { | |
| 500 | - console.log('云台控制:' + command); | |
| 501 | - let that = this; | |
| 502 | - this.$axios({ | |
| 503 | - method: 'post', | |
| 504 | - url: '/api/ptz/control/' + this.deviceId + '/' + this.channelId + '?command=' + command + '&horizonSpeed=' + this.controSpeed + '&verticalSpeed=' + this.controSpeed + '&zoomSpeed=' + this.controSpeed | |
| 505 | - }).then(function (res) {}); | |
| 506 | - }, | |
| 507 | - //////////////////////播放器事件处理////////////////////////// | |
| 508 | - videoError: function (e) { | |
| 509 | - console.log("播放器错误:" + JSON.stringify(e)); | |
| 510 | - }, | |
| 511 | - presetPosition: function (cmdCode, presetPos) { | |
| 512 | - console.log('预置位控制:' + this.presetPos + ' : 0x' + cmdCode.toString(16)); | |
| 513 | - let that = this; | |
| 514 | - this.$axios({ | |
| 515 | - method: 'post', | |
| 516 | - url: '/api/ptz/front_end_command/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '¶meter1=0¶meter2=' + presetPos + '&combindCode2=0' | |
| 517 | - }).then(function (res) {}); | |
| 518 | - }, | |
| 519 | - setSpeedOrTime: function (cmdCode, groupNum, parameter) { | |
| 520 | - let that = this; | |
| 521 | - let parameter2 = parameter % 256; | |
| 522 | - let combindCode2 = Math.floor(parameter / 256) * 16; | |
| 523 | - console.log('前端控制:0x' + cmdCode.toString(16) + ' 0x' + groupNum.toString(16) + ' 0x' + parameter2.toString(16) + ' 0x' + combindCode2.toString(16)); | |
| 524 | - this.$axios({ | |
| 525 | - method: 'post', | |
| 526 | - url: '/api/ptz/front_end_command/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '¶meter1=' + groupNum + '¶meter2=' + parameter2 + '&combindCode2=' + combindCode2 | |
| 527 | - }).then(function (res) {}); | |
| 528 | - }, | |
| 529 | - setCommand: function (cmdCode, groupNum, parameter) { | |
| 530 | - let that = this; | |
| 531 | - console.log('前端控制:0x' + cmdCode.toString(16) + ' 0x' + groupNum.toString(16) + ' 0x' + parameter.toString(16) + ' 0x0'); | |
| 532 | - this.$axios({ | |
| 533 | - method: 'post', | |
| 534 | - url: '/api/ptz/front_end_command/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '¶meter1=' + groupNum + '¶meter2=' + parameter + '&combindCode2=0' | |
| 535 | - }).then(function (res) {}); | |
| 536 | - }, | |
| 537 | - copyUrl: function (dropdownItem){ | |
| 538 | - console.log(dropdownItem) | |
| 539 | - this.$copyText(dropdownItem).then((e)=> { | |
| 540 | - this.$message.success("成功拷贝到粘贴板"); | |
| 541 | - }, (e)=> { | |
| 568 | + copySharedInfo: function (data) { | |
| 569 | + console.log('复制内容:' + data); | |
| 570 | + this.coverPlaying = false; | |
| 571 | + this.tracks = [] | |
| 572 | + let _this = this; | |
| 573 | + this.$copyText(data).then( | |
| 574 | + function (e) { | |
| 575 | + _this.$message({ | |
| 576 | + showClose: true, | |
| 577 | + message: '复制成功', | |
| 578 | + type: 'success' | |
| 579 | + }); | |
| 580 | + }, | |
| 581 | + function (e) { | |
| 582 | + _this.$message({ | |
| 583 | + showClose: true, | |
| 584 | + message: '复制失败,请手动复制', | |
| 585 | + type: 'error' | |
| 586 | + }); | |
| 587 | + } | |
| 588 | + ); | |
| 589 | + }, | |
| 590 | + ptzCamera: function (command) { | |
| 591 | + console.log('云台控制:' + command); | |
| 592 | + let that = this; | |
| 593 | + this.$axios({ | |
| 594 | + method: 'post', | |
| 595 | + url: '/api/ptz/control/' + this.deviceId + '/' + this.channelId + '?command=' + command + '&horizonSpeed=' + this.controSpeed + '&verticalSpeed=' + this.controSpeed + '&zoomSpeed=' + this.controSpeed | |
| 596 | + }).then(function (res) { | |
| 597 | + }); | |
| 598 | + }, | |
| 599 | + //////////////////////播放器事件处理////////////////////////// | |
| 600 | + videoError: function (e) { | |
| 601 | + console.log("播放器错误:" + JSON.stringify(e)); | |
| 602 | + }, | |
| 603 | + presetPosition: function (cmdCode, presetPos) { | |
| 604 | + console.log('预置位控制:' + this.presetPos + ' : 0x' + cmdCode.toString(16)); | |
| 605 | + let that = this; | |
| 606 | + this.$axios({ | |
| 607 | + method: 'post', | |
| 608 | + url: '/api/ptz/front_end_command/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '¶meter1=0¶meter2=' + presetPos + '&combindCode2=0' | |
| 609 | + }).then(function (res) { | |
| 610 | + }); | |
| 611 | + }, | |
| 612 | + setSpeedOrTime: function (cmdCode, groupNum, parameter) { | |
| 613 | + let that = this; | |
| 614 | + let parameter2 = parameter % 256; | |
| 615 | + let combindCode2 = Math.floor(parameter / 256) * 16; | |
| 616 | + console.log('前端控制:0x' + cmdCode.toString(16) + ' 0x' + groupNum.toString(16) + ' 0x' + parameter2.toString(16) + ' 0x' + combindCode2.toString(16)); | |
| 617 | + this.$axios({ | |
| 618 | + method: 'post', | |
| 619 | + url: '/api/ptz/front_end_command/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '¶meter1=' + groupNum + '¶meter2=' + parameter2 + '&combindCode2=' + combindCode2 | |
| 620 | + }).then(function (res) { | |
| 621 | + }); | |
| 622 | + }, | |
| 623 | + setCommand: function (cmdCode, groupNum, parameter) { | |
| 624 | + let that = this; | |
| 625 | + console.log('前端控制:0x' + cmdCode.toString(16) + ' 0x' + groupNum.toString(16) + ' 0x' + parameter.toString(16) + ' 0x0'); | |
| 626 | + this.$axios({ | |
| 627 | + method: 'post', | |
| 628 | + url: '/api/ptz/front_end_command/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '¶meter1=' + groupNum + '¶meter2=' + parameter + '&combindCode2=0' | |
| 629 | + }).then(function (res) { | |
| 630 | + }); | |
| 631 | + }, | |
| 632 | + copyUrl: function (dropdownItem) { | |
| 633 | + console.log(dropdownItem) | |
| 634 | + this.$copyText(dropdownItem).then((e) => { | |
| 635 | + this.$message.success("成功拷贝到粘贴板"); | |
| 636 | + }, (e) => { | |
| 542 | 637 | |
| 543 | - }) | |
| 544 | - }, | |
| 638 | + }) | |
| 639 | + }, | |
| 640 | + getBroadcastStatus() { | |
| 641 | + if (this.broadcastStatus == -2) { | |
| 642 | + return "primary" | |
| 643 | + } | |
| 644 | + if (this.broadcastStatus == -1) { | |
| 645 | + return "primary" | |
| 646 | + } | |
| 647 | + if (this.broadcastStatus == 0) { | |
| 648 | + return "warning" | |
| 649 | + } | |
| 650 | + if (this.broadcastStatus == 1) { | |
| 651 | + return "danger" | |
| 652 | + } | |
| 545 | 653 | |
| 654 | + }, | |
| 655 | + broadcastStatusClick() { | |
| 656 | + if (this.broadcastStatus == -1) { | |
| 657 | + // 默认状态, 开始 | |
| 658 | + this.broadcastStatus = 0 | |
| 659 | + // 发起语音对讲 | |
| 660 | + this.$axios({ | |
| 661 | + method: 'get', | |
| 662 | + url: '/api/play/broadcast/' + this.deviceId + '/' + this.channelId + "?timeout=30&broadcastMode=" + this.broadcastMode | |
| 663 | + }).then((res) => { | |
| 664 | + if (res.data.code === 0) { | |
| 665 | + let streamInfo = res.data.data.streamInfo; | |
| 666 | + if (document.location.protocol.includes("https")) { | |
| 667 | + this.startBroadcast(streamInfo.rtcs) | |
| 668 | + } else { | |
| 669 | + this.startBroadcast(streamInfo.rtc) | |
| 670 | + } | |
| 671 | + } else { | |
| 672 | + this.$message({ | |
| 673 | + showClose: true, | |
| 674 | + message: res.data.msg, | |
| 675 | + type: "error", | |
| 676 | + }); | |
| 677 | + } | |
| 678 | + }); | |
| 679 | + } else if (this.broadcastStatus === 1) { | |
| 680 | + this.broadcastStatus = -1; | |
| 681 | + this.broadcastRtc.close() | |
| 682 | + } | |
| 683 | + }, | |
| 684 | + startBroadcast(url) { | |
| 685 | + // 获取推流鉴权Key | |
| 686 | + this.$axios({ | |
| 687 | + method: 'post', | |
| 688 | + url: '/api/user/userInfo', | |
| 689 | + }).then((res) => { | |
| 690 | + if (res.data.code !== 0) { | |
| 691 | + this.$message({ | |
| 692 | + showClose: true, | |
| 693 | + message: "获取推流鉴权Key失败", | |
| 694 | + type: "error", | |
| 695 | + }); | |
| 696 | + this.broadcastStatus = -1; | |
| 697 | + } else { | |
| 698 | + let pushKey = res.data.data.pushKey; | |
| 699 | + // 获取推流鉴权KEY | |
| 700 | + url += "&sign=" + crypto.createHash('md5').update(pushKey, "utf8").digest('hex') | |
| 701 | + console.log("开始语音喊话: " + url) | |
| 702 | + this.broadcastRtc = new ZLMRTCClient.Endpoint({ | |
| 703 | + debug: true, // 是否打印日志 | |
| 704 | + zlmsdpUrl: url, //流地址 | |
| 705 | + simulecast: false, | |
| 706 | + useCamera: false, | |
| 707 | + audioEnable: true, | |
| 708 | + videoEnable: false, | |
| 709 | + recvOnly: false, | |
| 710 | + }) | |
| 711 | + | |
| 712 | + // webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_ON_REMOTE_STREAMS,(e)=>{//获取到了远端流,可以播放 | |
| 713 | + // console.error('播放成功',e.streams) | |
| 714 | + // this.broadcastStatus = 1; | |
| 715 | + // }); | |
| 716 | + // | |
| 717 | + // webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_ON_LOCAL_STREAM,(s)=>{// 获取到了本地流 | |
| 718 | + // this.broadcastStatus = 1; | |
| 719 | + // // document.getElementById('selfVideo').srcObject=s; | |
| 720 | + // // this.eventcallbacK("LOCAL STREAM", "获取到了本地流") | |
| 721 | + // }); | |
| 722 | + | |
| 723 | + this.broadcastRtc.on(ZLMRTCClient.Events.WEBRTC_NOT_SUPPORT, (e) => {// 获取到了本地流 | |
| 724 | + console.error('不支持webrtc', e) | |
| 725 | + this.$message({ | |
| 726 | + showClose: true, | |
| 727 | + message: '不支持webrtc, 无法进行语音喊话', | |
| 728 | + type: 'error' | |
| 729 | + }); | |
| 730 | + this.broadcastStatus = -1; | |
| 731 | + }); | |
| 732 | + | |
| 733 | + this.broadcastRtc.on(ZLMRTCClient.Events.WEBRTC_ICE_CANDIDATE_ERROR, (e) => {// ICE 协商出错 | |
| 734 | + console.error('ICE 协商出错') | |
| 735 | + this.$message({ | |
| 736 | + showClose: true, | |
| 737 | + message: 'ICE 协商出错', | |
| 738 | + type: 'error' | |
| 739 | + }); | |
| 740 | + this.broadcastStatus = -1; | |
| 741 | + }); | |
| 742 | + | |
| 743 | + this.broadcastRtc.on(ZLMRTCClient.Events.WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED, (e) => {// offer anwser 交换失败 | |
| 744 | + console.error('offer anwser 交换失败', e) | |
| 745 | + this.$message({ | |
| 746 | + showClose: true, | |
| 747 | + message: 'offer anwser 交换失败' + e, | |
| 748 | + type: 'error' | |
| 749 | + }); | |
| 750 | + this.broadcastStatus = -1; | |
| 751 | + }); | |
| 752 | + this.broadcastRtc.on(ZLMRTCClient.Events.WEBRTC_ON_CONNECTION_STATE_CHANGE, (e) => {// offer anwser 交换失败 | |
| 753 | + console.log('状态改变', e) | |
| 754 | + if (e === "connecting") { | |
| 755 | + this.broadcastStatus = 0; | |
| 756 | + } else if (e === "connected") { | |
| 757 | + this.broadcastStatus = 1; | |
| 758 | + } else if (e === "disconnected") { | |
| 759 | + this.broadcastStatus = -1; | |
| 760 | + } | |
| 761 | + }); | |
| 762 | + this.broadcastRtc.on(ZLMRTCClient.Events.CAPTURE_STREAM_FAILED, (e) => {// offer anwser 交换失败 | |
| 763 | + console.log('捕获流失败', e) | |
| 764 | + this.$message({ | |
| 765 | + showClose: true, | |
| 766 | + message: '捕获流失败' + e, | |
| 767 | + type: 'error' | |
| 768 | + }); | |
| 769 | + this.broadcastStatus = -1; | |
| 770 | + }); | |
| 771 | + } | |
| 772 | + }).catch((e) => { | |
| 773 | + this.$message({ | |
| 774 | + showClose: true, | |
| 775 | + message: e, | |
| 776 | + type: 'error' | |
| 777 | + }); | |
| 778 | + this.broadcastStatus = -1; | |
| 779 | + }); | |
| 546 | 780 | |
| 547 | 781 | |
| 782 | + }, | |
| 783 | + stopBroadcast() { | |
| 784 | + this.broadcastRtc.close(); | |
| 785 | + this.broadcastStatus = -1; | |
| 786 | + this.$axios({ | |
| 787 | + method: 'get', | |
| 788 | + url: '/api/play/broadcast/stop/' + this.deviceId + '/' + this.channelId | |
| 789 | + }).then((res) => { | |
| 790 | + if (res.data.code == 0) { | |
| 791 | + // this.broadcastStatus = -1; | |
| 792 | + // this.broadcastRtc.close() | |
| 793 | + } else { | |
| 794 | + this.$message({ | |
| 795 | + showClose: true, | |
| 796 | + message: res.data.msg, | |
| 797 | + type: "error", | |
| 798 | + }); | |
| 799 | + } | |
| 800 | + }); | |
| 548 | 801 | } |
| 802 | + } | |
| 549 | 803 | }; |
| 550 | 804 | </script> |
| 551 | 805 | |
| 552 | 806 | <style> |
| 553 | 807 | .control-wrapper { |
| 554 | - position: relative; | |
| 555 | - width: 6.25rem; | |
| 556 | - height: 6.25rem; | |
| 557 | - max-width: 6.25rem; | |
| 558 | - max-height: 6.25rem; | |
| 559 | - border-radius: 100%; | |
| 560 | - margin-top: 1.5rem; | |
| 561 | - margin-left: 0.5rem; | |
| 562 | - float: left; | |
| 808 | + position: relative; | |
| 809 | + width: 6.25rem; | |
| 810 | + height: 6.25rem; | |
| 811 | + max-width: 6.25rem; | |
| 812 | + max-height: 6.25rem; | |
| 813 | + border-radius: 100%; | |
| 814 | + margin-top: 1.5rem; | |
| 815 | + margin-left: 0.5rem; | |
| 816 | + float: left; | |
| 563 | 817 | } |
| 564 | 818 | |
| 565 | 819 | .control-panel { |
| 566 | - position: relative; | |
| 567 | - top: 0; | |
| 568 | - left: 5rem; | |
| 569 | - height: 11rem; | |
| 570 | - max-height: 11rem; | |
| 820 | + position: relative; | |
| 821 | + top: 0; | |
| 822 | + left: 5rem; | |
| 823 | + height: 11rem; | |
| 824 | + max-height: 11rem; | |
| 571 | 825 | } |
| 572 | 826 | |
| 573 | 827 | .control-btn { |
| 574 | - display: flex; | |
| 575 | - justify-content: center; | |
| 576 | - position: absolute; | |
| 577 | - width: 44%; | |
| 578 | - height: 44%; | |
| 579 | - border-radius: 5px; | |
| 580 | - border: 1px solid #78aee4; | |
| 581 | - box-sizing: border-box; | |
| 582 | - transition: all 0.3s linear; | |
| 828 | + display: flex; | |
| 829 | + justify-content: center; | |
| 830 | + position: absolute; | |
| 831 | + width: 44%; | |
| 832 | + height: 44%; | |
| 833 | + border-radius: 5px; | |
| 834 | + border: 1px solid #78aee4; | |
| 835 | + box-sizing: border-box; | |
| 836 | + transition: all 0.3s linear; | |
| 583 | 837 | } |
| 838 | + | |
| 584 | 839 | .control-btn:hover { |
| 585 | - cursor:pointer | |
| 840 | + cursor: pointer | |
| 586 | 841 | } |
| 587 | 842 | |
| 588 | 843 | .control-btn i { |
| 589 | - font-size: 20px; | |
| 590 | - color: #78aee4; | |
| 591 | - display: flex; | |
| 592 | - justify-content: center; | |
| 593 | - align-items: center; | |
| 844 | + font-size: 20px; | |
| 845 | + color: #78aee4; | |
| 846 | + display: flex; | |
| 847 | + justify-content: center; | |
| 848 | + align-items: center; | |
| 594 | 849 | } |
| 850 | + | |
| 595 | 851 | .control-btn i:hover { |
| 596 | - cursor:pointer | |
| 852 | + cursor: pointer | |
| 597 | 853 | } |
| 854 | + | |
| 598 | 855 | .control-zoom-btn:hover { |
| 599 | - cursor:pointer | |
| 856 | + cursor: pointer | |
| 600 | 857 | } |
| 601 | 858 | |
| 602 | 859 | .control-round { |
| 603 | - position: absolute; | |
| 604 | - top: 21%; | |
| 605 | - left: 21%; | |
| 606 | - width: 58%; | |
| 607 | - height: 58%; | |
| 608 | - background: #fff; | |
| 609 | - border-radius: 100%; | |
| 860 | + position: absolute; | |
| 861 | + top: 21%; | |
| 862 | + left: 21%; | |
| 863 | + width: 58%; | |
| 864 | + height: 58%; | |
| 865 | + background: #fff; | |
| 866 | + border-radius: 100%; | |
| 610 | 867 | } |
| 611 | 868 | |
| 612 | 869 | .control-round-inner { |
| 613 | - position: absolute; | |
| 614 | - left: 13%; | |
| 615 | - top: 13%; | |
| 616 | - display: flex; | |
| 617 | - justify-content: center; | |
| 618 | - align-items: center; | |
| 619 | - width: 70%; | |
| 620 | - height: 70%; | |
| 621 | - font-size: 40px; | |
| 622 | - color: #78aee4; | |
| 623 | - border: 1px solid #78aee4; | |
| 624 | - border-radius: 100%; | |
| 625 | - transition: all 0.3s linear; | |
| 870 | + position: absolute; | |
| 871 | + left: 13%; | |
| 872 | + top: 13%; | |
| 873 | + display: flex; | |
| 874 | + justify-content: center; | |
| 875 | + align-items: center; | |
| 876 | + width: 70%; | |
| 877 | + height: 70%; | |
| 878 | + font-size: 40px; | |
| 879 | + color: #78aee4; | |
| 880 | + border: 1px solid #78aee4; | |
| 881 | + border-radius: 100%; | |
| 882 | + transition: all 0.3s linear; | |
| 626 | 883 | } |
| 627 | 884 | |
| 628 | 885 | .control-inner-btn { |
| 629 | - position: absolute; | |
| 630 | - width: 60%; | |
| 631 | - height: 60%; | |
| 632 | - background: #fafafa; | |
| 886 | + position: absolute; | |
| 887 | + width: 60%; | |
| 888 | + height: 60%; | |
| 889 | + background: #fafafa; | |
| 633 | 890 | } |
| 634 | 891 | |
| 635 | 892 | .control-top { |
| 636 | - top: -8%; | |
| 637 | - left: 27%; | |
| 638 | - transform: rotate(-45deg); | |
| 639 | - border-radius: 5px 100% 5px 0; | |
| 893 | + top: -8%; | |
| 894 | + left: 27%; | |
| 895 | + transform: rotate(-45deg); | |
| 896 | + border-radius: 5px 100% 5px 0; | |
| 640 | 897 | } |
| 641 | 898 | |
| 642 | 899 | .control-top i { |
| 643 | - transform: rotate(45deg); | |
| 644 | - border-radius: 5px 100% 5px 0; | |
| 900 | + transform: rotate(45deg); | |
| 901 | + border-radius: 5px 100% 5px 0; | |
| 645 | 902 | } |
| 646 | 903 | |
| 647 | 904 | .control-top .control-inner { |
| 648 | - left: -1px; | |
| 649 | - bottom: 0; | |
| 650 | - border-top: 1px solid #78aee4; | |
| 651 | - border-right: 1px solid #78aee4; | |
| 652 | - border-radius: 0 100% 0 0; | |
| 905 | + left: -1px; | |
| 906 | + bottom: 0; | |
| 907 | + border-top: 1px solid #78aee4; | |
| 908 | + border-right: 1px solid #78aee4; | |
| 909 | + border-radius: 0 100% 0 0; | |
| 653 | 910 | } |
| 654 | 911 | |
| 655 | 912 | .control-top .fa { |
| 656 | - transform: rotate(45deg) translateY(-7px); | |
| 913 | + transform: rotate(45deg) translateY(-7px); | |
| 657 | 914 | } |
| 658 | 915 | |
| 659 | 916 | .control-left { |
| 660 | - top: 27%; | |
| 661 | - left: -8%; | |
| 662 | - transform: rotate(45deg); | |
| 663 | - border-radius: 5px 0 5px 100%; | |
| 917 | + top: 27%; | |
| 918 | + left: -8%; | |
| 919 | + transform: rotate(45deg); | |
| 920 | + border-radius: 5px 0 5px 100%; | |
| 664 | 921 | } |
| 665 | 922 | |
| 666 | 923 | .control-left i { |
| 667 | - transform: rotate(-45deg); | |
| 924 | + transform: rotate(-45deg); | |
| 668 | 925 | } |
| 669 | 926 | |
| 670 | 927 | .control-left .control-inner { |
| 671 | - right: -1px; | |
| 672 | - top: -1px; | |
| 673 | - border-bottom: 1px solid #78aee4; | |
| 674 | - border-left: 1px solid #78aee4; | |
| 675 | - border-radius: 0 0 0 100%; | |
| 928 | + right: -1px; | |
| 929 | + top: -1px; | |
| 930 | + border-bottom: 1px solid #78aee4; | |
| 931 | + border-left: 1px solid #78aee4; | |
| 932 | + border-radius: 0 0 0 100%; | |
| 676 | 933 | } |
| 677 | 934 | |
| 678 | 935 | .control-left .fa { |
| 679 | - transform: rotate(-45deg) translateX(-7px); | |
| 936 | + transform: rotate(-45deg) translateX(-7px); | |
| 680 | 937 | } |
| 681 | 938 | |
| 682 | 939 | .control-right { |
| 683 | - top: 27%; | |
| 684 | - right: -8%; | |
| 685 | - transform: rotate(45deg); | |
| 686 | - border-radius: 5px 100% 5px 0; | |
| 940 | + top: 27%; | |
| 941 | + right: -8%; | |
| 942 | + transform: rotate(45deg); | |
| 943 | + border-radius: 5px 100% 5px 0; | |
| 687 | 944 | } |
| 688 | 945 | |
| 689 | 946 | .control-right i { |
| 690 | - transform: rotate(-45deg); | |
| 947 | + transform: rotate(-45deg); | |
| 691 | 948 | } |
| 692 | 949 | |
| 693 | 950 | .control-right .control-inner { |
| 694 | - left: -1px; | |
| 695 | - bottom: -1px; | |
| 696 | - border-top: 1px solid #78aee4; | |
| 697 | - border-right: 1px solid #78aee4; | |
| 698 | - border-radius: 0 100% 0 0; | |
| 951 | + left: -1px; | |
| 952 | + bottom: -1px; | |
| 953 | + border-top: 1px solid #78aee4; | |
| 954 | + border-right: 1px solid #78aee4; | |
| 955 | + border-radius: 0 100% 0 0; | |
| 699 | 956 | } |
| 700 | 957 | |
| 701 | 958 | .control-right .fa { |
| 702 | - transform: rotate(-45deg) translateX(7px); | |
| 959 | + transform: rotate(-45deg) translateX(7px); | |
| 703 | 960 | } |
| 704 | 961 | |
| 705 | 962 | .control-bottom { |
| 706 | - left: 27%; | |
| 707 | - bottom: -8%; | |
| 708 | - transform: rotate(45deg); | |
| 709 | - border-radius: 0 5px 100% 5px; | |
| 963 | + left: 27%; | |
| 964 | + bottom: -8%; | |
| 965 | + transform: rotate(45deg); | |
| 966 | + border-radius: 0 5px 100% 5px; | |
| 710 | 967 | } |
| 711 | 968 | |
| 712 | 969 | .control-bottom i { |
| 713 | - transform: rotate(-45deg); | |
| 970 | + transform: rotate(-45deg); | |
| 714 | 971 | } |
| 715 | 972 | |
| 716 | 973 | .control-bottom .control-inner { |
| 717 | - top: -1px; | |
| 718 | - left: -1px; | |
| 719 | - border-bottom: 1px solid #78aee4; | |
| 720 | - border-right: 1px solid #78aee4; | |
| 721 | - border-radius: 0 0 100% 0; | |
| 974 | + top: -1px; | |
| 975 | + left: -1px; | |
| 976 | + border-bottom: 1px solid #78aee4; | |
| 977 | + border-right: 1px solid #78aee4; | |
| 978 | + border-radius: 0 0 100% 0; | |
| 722 | 979 | } |
| 723 | 980 | |
| 724 | 981 | .control-bottom .fa { |
| 725 | - transform: rotate(-45deg) translateY(7px); | |
| 982 | + transform: rotate(-45deg) translateY(7px); | |
| 726 | 983 | } |
| 984 | + | |
| 727 | 985 | .trank { |
| 728 | - width: 80%; | |
| 729 | - height: 180px; | |
| 730 | - text-align: left; | |
| 731 | - padding: 0 10%; | |
| 732 | - overflow: auto; | |
| 986 | + width: 80%; | |
| 987 | + height: 180px; | |
| 988 | + text-align: left; | |
| 989 | + padding: 0 10%; | |
| 990 | + overflow: auto; | |
| 733 | 991 | } |
| 992 | + | |
| 734 | 993 | .trankInfo { |
| 735 | - width: 80%; | |
| 736 | - padding: 0 10%; | |
| 994 | + width: 80%; | |
| 995 | + padding: 0 10%; | |
| 737 | 996 | } |
| 738 | 997 | </style> | ... | ... |
web_src/static/js/ZLMRTCClient.js
| ... | ... | @@ -15,26 +15,28 @@ var ZLMRTCClient = (function (exports) { |
| 15 | 15 | CAPTURE_STREAM_FAILED: 'CAPTURE_STREAM_FAILED' |
| 16 | 16 | }; |
| 17 | 17 | |
| 18 | - const VERSION = '1.0.1'; | |
| 19 | - const BUILD_DATE = 'Thu Mar 24 2022 17:42:57 GMT+0800 (China Standard Time)'; | |
| 18 | + const VERSION$1 = '1.0.1'; | |
| 19 | + const BUILD_DATE = 'Mon Mar 27 2023 19:11:59 GMT+0800 (China Standard Time)'; | |
| 20 | 20 | |
| 21 | 21 | // Copyright (C) <2018> Intel Corporation |
| 22 | 22 | // |
| 23 | 23 | // SPDX-License-Identifier: Apache-2.0 |
| 24 | + | |
| 24 | 25 | // eslint-disable-next-line require-jsdoc |
| 25 | 26 | function isFirefox() { |
| 26 | 27 | return window.navigator.userAgent.match('Firefox') !== null; |
| 27 | - } // eslint-disable-next-line require-jsdoc | |
| 28 | - | |
| 28 | + } | |
| 29 | + // eslint-disable-next-line require-jsdoc | |
| 29 | 30 | function isChrome() { |
| 30 | 31 | return window.navigator.userAgent.match('Chrome') !== null; |
| 31 | - } // eslint-disable-next-line require-jsdoc | |
| 32 | - | |
| 32 | + } | |
| 33 | + // eslint-disable-next-line require-jsdoc | |
| 33 | 34 | function isEdge() { |
| 34 | 35 | return window.navigator.userAgent.match(/Edge\/(\d+).(\d+)$/) !== null; |
| 35 | - } // eslint-disable-next-line require-jsdoc | |
| 36 | + } | |
| 36 | 37 | |
| 37 | 38 | // Copyright (C) <2018> Intel Corporation |
| 39 | + | |
| 38 | 40 | /** |
| 39 | 41 | * @class AudioSourceInfo |
| 40 | 42 | * @classDesc Source info about an audio track. Values: 'mic', 'screen-cast', 'file', 'mixed'. |
| ... | ... | @@ -42,13 +44,13 @@ var ZLMRTCClient = (function (exports) { |
| 42 | 44 | * @readonly |
| 43 | 45 | * @enum {string} |
| 44 | 46 | */ |
| 45 | - | |
| 46 | 47 | const AudioSourceInfo = { |
| 47 | 48 | MIC: 'mic', |
| 48 | 49 | SCREENCAST: 'screen-cast', |
| 49 | 50 | FILE: 'file', |
| 50 | 51 | MIXED: 'mixed' |
| 51 | 52 | }; |
| 53 | + | |
| 52 | 54 | /** |
| 53 | 55 | * @class VideoSourceInfo |
| 54 | 56 | * @classDesc Source info about a video track. Values: 'camera', 'screen-cast', 'file', 'mixed'. |
| ... | ... | @@ -56,13 +58,13 @@ var ZLMRTCClient = (function (exports) { |
| 56 | 58 | * @readonly |
| 57 | 59 | * @enum {string} |
| 58 | 60 | */ |
| 59 | - | |
| 60 | 61 | const VideoSourceInfo = { |
| 61 | 62 | CAMERA: 'camera', |
| 62 | 63 | SCREENCAST: 'screen-cast', |
| 63 | 64 | FILE: 'file', |
| 64 | 65 | MIXED: 'mixed' |
| 65 | 66 | }; |
| 67 | + | |
| 66 | 68 | /** |
| 67 | 69 | * @class TrackKind |
| 68 | 70 | * @classDesc Kind of a track. Values: 'audio' for audio track, 'video' for video track, 'av' for both audio and video tracks. |
| ... | ... | @@ -70,20 +72,17 @@ var ZLMRTCClient = (function (exports) { |
| 70 | 72 | * @readonly |
| 71 | 73 | * @enum {string} |
| 72 | 74 | */ |
| 73 | - | |
| 74 | 75 | const TrackKind = { |
| 75 | 76 | /** |
| 76 | 77 | * Audio tracks. |
| 77 | 78 | * @type string |
| 78 | 79 | */ |
| 79 | 80 | AUDIO: 'audio', |
| 80 | - | |
| 81 | 81 | /** |
| 82 | 82 | * Video tracks. |
| 83 | 83 | * @type string |
| 84 | 84 | */ |
| 85 | 85 | VIDEO: 'video', |
| 86 | - | |
| 87 | 86 | /** |
| 88 | 87 | * Both audio and video tracks. |
| 89 | 88 | * @type string |
| ... | ... | @@ -98,7 +97,6 @@ var ZLMRTCClient = (function (exports) { |
| 98 | 97 | * @param {number} width |
| 99 | 98 | * @param {number} height |
| 100 | 99 | */ |
| 101 | - | |
| 102 | 100 | class Resolution { |
| 103 | 101 | // eslint-disable-next-line require-jsdoc |
| 104 | 102 | constructor(width, height) { |
| ... | ... | @@ -113,10 +111,8 @@ var ZLMRTCClient = (function (exports) { |
| 113 | 111 | * @instance |
| 114 | 112 | * @memberof Owt.Base.Resolution |
| 115 | 113 | */ |
| 116 | - | |
| 117 | 114 | this.height = height; |
| 118 | 115 | } |
| 119 | - | |
| 120 | 116 | } |
| 121 | 117 | |
| 122 | 118 | /* |
| ... | ... | @@ -5531,7 +5527,6 @@ var ZLMRTCClient = (function (exports) { |
| 5531 | 5527 | * @constructor |
| 5532 | 5528 | * @param {Owt.Base.AudioSourceInfo} source Source info of this audio track. |
| 5533 | 5529 | */ |
| 5534 | - | |
| 5535 | 5530 | class AudioTrackConstraints { |
| 5536 | 5531 | // eslint-disable-next-line require-jsdoc |
| 5537 | 5532 | constructor(source) { |
| ... | ... | @@ -5544,8 +5539,6 @@ var ZLMRTCClient = (function (exports) { |
| 5544 | 5539 | * @desc Values could be "mic", "screen-cast", "file" or "mixed". |
| 5545 | 5540 | * @instance |
| 5546 | 5541 | */ |
| 5547 | - | |
| 5548 | - | |
| 5549 | 5542 | this.source = source; |
| 5550 | 5543 | /** |
| 5551 | 5544 | * @member {string} deviceId |
| ... | ... | @@ -5554,11 +5547,10 @@ var ZLMRTCClient = (function (exports) { |
| 5554 | 5547 | * @instance |
| 5555 | 5548 | * @see https://w3c.github.io/mediacapture-main/#def-constraint-deviceId |
| 5556 | 5549 | */ |
| 5557 | - | |
| 5558 | 5550 | this.deviceId = undefined; |
| 5559 | 5551 | } |
| 5560 | - | |
| 5561 | 5552 | } |
| 5553 | + | |
| 5562 | 5554 | /** |
| 5563 | 5555 | * @class VideoTrackConstraints |
| 5564 | 5556 | * @classDesc Constraints for creating a video MediaStreamTrack. |
| ... | ... | @@ -5566,7 +5558,6 @@ var ZLMRTCClient = (function (exports) { |
| 5566 | 5558 | * @constructor |
| 5567 | 5559 | * @param {Owt.Base.VideoSourceInfo} source Source info of this video track. |
| 5568 | 5560 | */ |
| 5569 | - | |
| 5570 | 5561 | class VideoTrackConstraints { |
| 5571 | 5562 | // eslint-disable-next-line require-jsdoc |
| 5572 | 5563 | constructor(source) { |
| ... | ... | @@ -5579,8 +5570,6 @@ var ZLMRTCClient = (function (exports) { |
| 5579 | 5570 | * @desc Values could be "camera", "screen-cast", "file" or "mixed". |
| 5580 | 5571 | * @instance |
| 5581 | 5572 | */ |
| 5582 | - | |
| 5583 | - | |
| 5584 | 5573 | this.source = source; |
| 5585 | 5574 | /** |
| 5586 | 5575 | * @member {string} deviceId |
| ... | ... | @@ -5591,22 +5580,21 @@ var ZLMRTCClient = (function (exports) { |
| 5591 | 5580 | */ |
| 5592 | 5581 | |
| 5593 | 5582 | this.deviceId = undefined; |
| 5583 | + | |
| 5594 | 5584 | /** |
| 5595 | 5585 | * @member {Owt.Base.Resolution} resolution |
| 5596 | 5586 | * @memberof Owt.Base.VideoTrackConstraints |
| 5597 | 5587 | * @instance |
| 5598 | 5588 | */ |
| 5599 | - | |
| 5600 | 5589 | this.resolution = undefined; |
| 5590 | + | |
| 5601 | 5591 | /** |
| 5602 | 5592 | * @member {number} frameRate |
| 5603 | 5593 | * @memberof Owt.Base.VideoTrackConstraints |
| 5604 | 5594 | * @instance |
| 5605 | 5595 | */ |
| 5606 | - | |
| 5607 | 5596 | this.frameRate = undefined; |
| 5608 | 5597 | } |
| 5609 | - | |
| 5610 | 5598 | } |
| 5611 | 5599 | /** |
| 5612 | 5600 | * @class StreamConstraints |
| ... | ... | @@ -5616,7 +5604,6 @@ var ZLMRTCClient = (function (exports) { |
| 5616 | 5604 | * @param {?Owt.Base.AudioTrackConstraints} audioConstraints |
| 5617 | 5605 | * @param {?Owt.Base.VideoTrackConstraints} videoConstraints |
| 5618 | 5606 | */ |
| 5619 | - | |
| 5620 | 5607 | class StreamConstraints { |
| 5621 | 5608 | // eslint-disable-next-line require-jsdoc |
| 5622 | 5609 | constructor(audioConstraints = false, videoConstraints = false) { |
| ... | ... | @@ -5631,22 +5618,20 @@ var ZLMRTCClient = (function (exports) { |
| 5631 | 5618 | * @memberof Owt.Base.MediaStreamDeviceConstraints |
| 5632 | 5619 | * @instance |
| 5633 | 5620 | */ |
| 5634 | - | |
| 5635 | 5621 | this.video = videoConstraints; |
| 5636 | 5622 | } |
| 5623 | + } | |
| 5637 | 5624 | |
| 5638 | - } // eslint-disable-next-line require-jsdoc | |
| 5639 | - | |
| 5625 | + // eslint-disable-next-line require-jsdoc | |
| 5640 | 5626 | function isVideoConstrainsForScreenCast(constraints) { |
| 5641 | 5627 | return typeof constraints.video === 'object' && constraints.video.source === VideoSourceInfo.SCREENCAST; |
| 5642 | 5628 | } |
| 5629 | + | |
| 5643 | 5630 | /** |
| 5644 | 5631 | * @class MediaStreamFactory |
| 5645 | 5632 | * @classDesc A factory to create MediaStream. You can also create MediaStream by yourself. |
| 5646 | 5633 | * @memberof Owt.Base |
| 5647 | 5634 | */ |
| 5648 | - | |
| 5649 | - | |
| 5650 | 5635 | class MediaStreamFactory { |
| 5651 | 5636 | /** |
| 5652 | 5637 | * @function createMediaStream |
| ... | ... | @@ -5665,29 +5650,23 @@ var ZLMRTCClient = (function (exports) { |
| 5665 | 5650 | if (typeof constraints !== 'object' || !constraints.audio && !constraints.video) { |
| 5666 | 5651 | return Promise.reject(new TypeError('Invalid constrains')); |
| 5667 | 5652 | } |
| 5668 | - | |
| 5669 | 5653 | if (!isVideoConstrainsForScreenCast(constraints) && typeof constraints.audio === 'object' && constraints.audio.source === AudioSourceInfo.SCREENCAST) { |
| 5670 | 5654 | return Promise.reject(new TypeError('Cannot share screen without video.')); |
| 5671 | 5655 | } |
| 5672 | - | |
| 5673 | 5656 | if (isVideoConstrainsForScreenCast(constraints) && !isChrome() && !isFirefox()) { |
| 5674 | 5657 | return Promise.reject(new TypeError('Screen sharing only supports Chrome and Firefox.')); |
| 5675 | 5658 | } |
| 5676 | - | |
| 5677 | 5659 | if (isVideoConstrainsForScreenCast(constraints) && typeof constraints.audio === 'object' && constraints.audio.source !== AudioSourceInfo.SCREENCAST) { |
| 5678 | 5660 | return Promise.reject(new TypeError('Cannot capture video from screen cast while capture audio from' + ' other source.')); |
| 5679 | - } // Check and convert constraints. | |
| 5680 | - | |
| 5661 | + } | |
| 5681 | 5662 | |
| 5663 | + // Check and convert constraints. | |
| 5682 | 5664 | if (!constraints.audio && !constraints.video) { |
| 5683 | 5665 | return Promise.reject(new TypeError('At least one of audio and video must be requested.')); |
| 5684 | 5666 | } |
| 5685 | - | |
| 5686 | 5667 | const mediaConstraints = Object.create({}); |
| 5687 | - | |
| 5688 | 5668 | if (typeof constraints.audio === 'object' && constraints.audio.source === AudioSourceInfo.MIC) { |
| 5689 | 5669 | mediaConstraints.audio = Object.create({}); |
| 5690 | - | |
| 5691 | 5670 | if (isEdge()) { |
| 5692 | 5671 | mediaConstraints.audio.deviceId = constraints.audio.deviceId; |
| 5693 | 5672 | } else { |
| ... | ... | @@ -5702,14 +5681,11 @@ var ZLMRTCClient = (function (exports) { |
| 5702 | 5681 | mediaConstraints.audio = constraints.audio; |
| 5703 | 5682 | } |
| 5704 | 5683 | } |
| 5705 | - | |
| 5706 | 5684 | if (typeof constraints.video === 'object') { |
| 5707 | 5685 | mediaConstraints.video = Object.create({}); |
| 5708 | - | |
| 5709 | 5686 | if (typeof constraints.video.frameRate === 'number') { |
| 5710 | 5687 | mediaConstraints.video.frameRate = constraints.video.frameRate; |
| 5711 | 5688 | } |
| 5712 | - | |
| 5713 | 5689 | if (constraints.video.resolution && constraints.video.resolution.width && constraints.video.resolution.height) { |
| 5714 | 5690 | if (constraints.video.source === VideoSourceInfo.SCREENCAST) { |
| 5715 | 5691 | mediaConstraints.video.width = constraints.video.resolution.width; |
| ... | ... | @@ -5721,27 +5697,23 @@ var ZLMRTCClient = (function (exports) { |
| 5721 | 5697 | mediaConstraints.video.height.exact = constraints.video.resolution.height; |
| 5722 | 5698 | } |
| 5723 | 5699 | } |
| 5724 | - | |
| 5725 | 5700 | if (typeof constraints.video.deviceId === 'string') { |
| 5726 | 5701 | mediaConstraints.video.deviceId = { |
| 5727 | 5702 | exact: constraints.video.deviceId |
| 5728 | 5703 | }; |
| 5729 | 5704 | } |
| 5730 | - | |
| 5731 | 5705 | if (isFirefox() && constraints.video.source === VideoSourceInfo.SCREENCAST) { |
| 5732 | 5706 | mediaConstraints.video.mediaSource = 'screen'; |
| 5733 | 5707 | } |
| 5734 | 5708 | } else { |
| 5735 | 5709 | mediaConstraints.video = constraints.video; |
| 5736 | 5710 | } |
| 5737 | - | |
| 5738 | 5711 | if (isVideoConstrainsForScreenCast(constraints)) { |
| 5739 | 5712 | return navigator.mediaDevices.getDisplayMedia(mediaConstraints); |
| 5740 | 5713 | } else { |
| 5741 | 5714 | return navigator.mediaDevices.getUserMedia(mediaConstraints); |
| 5742 | 5715 | } |
| 5743 | 5716 | } |
| 5744 | - | |
| 5745 | 5717 | } |
| 5746 | 5718 | |
| 5747 | 5719 | // Copyright (C) <2018> Intel Corporation |
| ... | ... | @@ -5782,34 +5754,26 @@ var ZLMRTCClient = (function (exports) { |
| 5782 | 5754 | this.listener = {}; |
| 5783 | 5755 | this.type = type | ''; |
| 5784 | 5756 | } |
| 5785 | - | |
| 5786 | 5757 | on(event, fn) { |
| 5787 | 5758 | if (!this.listener[event]) { |
| 5788 | 5759 | this.listener[event] = []; |
| 5789 | 5760 | } |
| 5790 | - | |
| 5791 | 5761 | this.listener[event].push(fn); |
| 5792 | 5762 | return true; |
| 5793 | 5763 | } |
| 5794 | - | |
| 5795 | 5764 | off(event, fn) { |
| 5796 | 5765 | if (this.listener[event]) { |
| 5797 | 5766 | var index = this.listener[event].indexOf(fn); |
| 5798 | - | |
| 5799 | 5767 | if (index > -1) { |
| 5800 | 5768 | this.listener[event].splice(index, 1); |
| 5801 | 5769 | } |
| 5802 | - | |
| 5803 | 5770 | return true; |
| 5804 | 5771 | } |
| 5805 | - | |
| 5806 | 5772 | return false; |
| 5807 | 5773 | } |
| 5808 | - | |
| 5809 | 5774 | offAll() { |
| 5810 | 5775 | this.listener = {}; |
| 5811 | 5776 | } |
| 5812 | - | |
| 5813 | 5777 | dispatch(event, data) { |
| 5814 | 5778 | if (this.listener[event]) { |
| 5815 | 5779 | this.listener[event].map(each => { |
| ... | ... | @@ -5817,10 +5781,8 @@ var ZLMRTCClient = (function (exports) { |
| 5817 | 5781 | }); |
| 5818 | 5782 | return true; |
| 5819 | 5783 | } |
| 5820 | - | |
| 5821 | 5784 | return false; |
| 5822 | 5785 | } |
| 5823 | - | |
| 5824 | 5786 | } |
| 5825 | 5787 | |
| 5826 | 5788 | var bind = function bind(fn, thisArg) { |
| ... | ... | @@ -5833,12 +5795,26 @@ var ZLMRTCClient = (function (exports) { |
| 5833 | 5795 | }; |
| 5834 | 5796 | }; |
| 5835 | 5797 | |
| 5836 | - /*global toString:true*/ | |
| 5837 | - | |
| 5838 | 5798 | // utils is a library of generic helper functions non-specific to axios |
| 5839 | 5799 | |
| 5840 | 5800 | var toString = Object.prototype.toString; |
| 5841 | 5801 | |
| 5802 | + // eslint-disable-next-line func-names | |
| 5803 | + var kindOf = (function(cache) { | |
| 5804 | + // eslint-disable-next-line func-names | |
| 5805 | + return function(thing) { | |
| 5806 | + var str = toString.call(thing); | |
| 5807 | + return cache[str] || (cache[str] = str.slice(8, -1).toLowerCase()); | |
| 5808 | + }; | |
| 5809 | + })(Object.create(null)); | |
| 5810 | + | |
| 5811 | + function kindOfTest(type) { | |
| 5812 | + type = type.toLowerCase(); | |
| 5813 | + return function isKindOf(thing) { | |
| 5814 | + return kindOf(thing) === type; | |
| 5815 | + }; | |
| 5816 | + } | |
| 5817 | + | |
| 5842 | 5818 | /** |
| 5843 | 5819 | * Determine if a value is an Array |
| 5844 | 5820 | * |
| ... | ... | @@ -5846,7 +5822,7 @@ var ZLMRTCClient = (function (exports) { |
| 5846 | 5822 | * @returns {boolean} True if value is an Array, otherwise false |
| 5847 | 5823 | */ |
| 5848 | 5824 | function isArray(val) { |
| 5849 | - return toString.call(val) === '[object Array]'; | |
| 5825 | + return Array.isArray(val); | |
| 5850 | 5826 | } |
| 5851 | 5827 | |
| 5852 | 5828 | /** |
| ... | ... | @@ -5873,22 +5849,12 @@ var ZLMRTCClient = (function (exports) { |
| 5873 | 5849 | /** |
| 5874 | 5850 | * Determine if a value is an ArrayBuffer |
| 5875 | 5851 | * |
| 5852 | + * @function | |
| 5876 | 5853 | * @param {Object} val The value to test |
| 5877 | 5854 | * @returns {boolean} True if value is an ArrayBuffer, otherwise false |
| 5878 | 5855 | */ |
| 5879 | - function isArrayBuffer(val) { | |
| 5880 | - return toString.call(val) === '[object ArrayBuffer]'; | |
| 5881 | - } | |
| 5856 | + var isArrayBuffer = kindOfTest('ArrayBuffer'); | |
| 5882 | 5857 | |
| 5883 | - /** | |
| 5884 | - * Determine if a value is a FormData | |
| 5885 | - * | |
| 5886 | - * @param {Object} val The value to test | |
| 5887 | - * @returns {boolean} True if value is an FormData, otherwise false | |
| 5888 | - */ | |
| 5889 | - function isFormData(val) { | |
| 5890 | - return (typeof FormData !== 'undefined') && (val instanceof FormData); | |
| 5891 | - } | |
| 5892 | 5858 | |
| 5893 | 5859 | /** |
| 5894 | 5860 | * Determine if a value is a view on an ArrayBuffer |
| ... | ... | @@ -5901,7 +5867,7 @@ var ZLMRTCClient = (function (exports) { |
| 5901 | 5867 | if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) { |
| 5902 | 5868 | result = ArrayBuffer.isView(val); |
| 5903 | 5869 | } else { |
| 5904 | - result = (val) && (val.buffer) && (val.buffer instanceof ArrayBuffer); | |
| 5870 | + result = (val) && (val.buffer) && (isArrayBuffer(val.buffer)); | |
| 5905 | 5871 | } |
| 5906 | 5872 | return result; |
| 5907 | 5873 | } |
| ... | ... | @@ -5943,7 +5909,7 @@ var ZLMRTCClient = (function (exports) { |
| 5943 | 5909 | * @return {boolean} True if value is a plain Object, otherwise false |
| 5944 | 5910 | */ |
| 5945 | 5911 | function isPlainObject(val) { |
| 5946 | - if (toString.call(val) !== '[object Object]') { | |
| 5912 | + if (kindOf(val) !== 'object') { | |
| 5947 | 5913 | return false; |
| 5948 | 5914 | } |
| 5949 | 5915 | |
| ... | ... | @@ -5954,32 +5920,38 @@ var ZLMRTCClient = (function (exports) { |
| 5954 | 5920 | /** |
| 5955 | 5921 | * Determine if a value is a Date |
| 5956 | 5922 | * |
| 5923 | + * @function | |
| 5957 | 5924 | * @param {Object} val The value to test |
| 5958 | 5925 | * @returns {boolean} True if value is a Date, otherwise false |
| 5959 | 5926 | */ |
| 5960 | - function isDate(val) { | |
| 5961 | - return toString.call(val) === '[object Date]'; | |
| 5962 | - } | |
| 5927 | + var isDate = kindOfTest('Date'); | |
| 5963 | 5928 | |
| 5964 | 5929 | /** |
| 5965 | 5930 | * Determine if a value is a File |
| 5966 | 5931 | * |
| 5932 | + * @function | |
| 5967 | 5933 | * @param {Object} val The value to test |
| 5968 | 5934 | * @returns {boolean} True if value is a File, otherwise false |
| 5969 | 5935 | */ |
| 5970 | - function isFile(val) { | |
| 5971 | - return toString.call(val) === '[object File]'; | |
| 5972 | - } | |
| 5936 | + var isFile = kindOfTest('File'); | |
| 5973 | 5937 | |
| 5974 | 5938 | /** |
| 5975 | 5939 | * Determine if a value is a Blob |
| 5976 | 5940 | * |
| 5941 | + * @function | |
| 5977 | 5942 | * @param {Object} val The value to test |
| 5978 | 5943 | * @returns {boolean} True if value is a Blob, otherwise false |
| 5979 | 5944 | */ |
| 5980 | - function isBlob(val) { | |
| 5981 | - return toString.call(val) === '[object Blob]'; | |
| 5982 | - } | |
| 5945 | + var isBlob = kindOfTest('Blob'); | |
| 5946 | + | |
| 5947 | + /** | |
| 5948 | + * Determine if a value is a FileList | |
| 5949 | + * | |
| 5950 | + * @function | |
| 5951 | + * @param {Object} val The value to test | |
| 5952 | + * @returns {boolean} True if value is a File, otherwise false | |
| 5953 | + */ | |
| 5954 | + var isFileList = kindOfTest('FileList'); | |
| 5983 | 5955 | |
| 5984 | 5956 | /** |
| 5985 | 5957 | * Determine if a value is a Function |
| ... | ... | @@ -6002,14 +5974,27 @@ var ZLMRTCClient = (function (exports) { |
| 6002 | 5974 | } |
| 6003 | 5975 | |
| 6004 | 5976 | /** |
| 6005 | - * Determine if a value is a URLSearchParams object | |
| 5977 | + * Determine if a value is a FormData | |
| 6006 | 5978 | * |
| 5979 | + * @param {Object} thing The value to test | |
| 5980 | + * @returns {boolean} True if value is an FormData, otherwise false | |
| 5981 | + */ | |
| 5982 | + function isFormData(thing) { | |
| 5983 | + var pattern = '[object FormData]'; | |
| 5984 | + return thing && ( | |
| 5985 | + (typeof FormData === 'function' && thing instanceof FormData) || | |
| 5986 | + toString.call(thing) === pattern || | |
| 5987 | + (isFunction(thing.toString) && thing.toString() === pattern) | |
| 5988 | + ); | |
| 5989 | + } | |
| 5990 | + | |
| 5991 | + /** | |
| 5992 | + * Determine if a value is a URLSearchParams object | |
| 5993 | + * @function | |
| 6007 | 5994 | * @param {Object} val The value to test |
| 6008 | 5995 | * @returns {boolean} True if value is a URLSearchParams object, otherwise false |
| 6009 | 5996 | */ |
| 6010 | - function isURLSearchParams(val) { | |
| 6011 | - return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams; | |
| 6012 | - } | |
| 5997 | + var isURLSearchParams = kindOfTest('URLSearchParams'); | |
| 6013 | 5998 | |
| 6014 | 5999 | /** |
| 6015 | 6000 | * Trim excess whitespace off the beginning and end of a string |
| ... | ... | @@ -6018,7 +6003,7 @@ var ZLMRTCClient = (function (exports) { |
| 6018 | 6003 | * @returns {String} The String freed of excess whitespace |
| 6019 | 6004 | */ |
| 6020 | 6005 | function trim(str) { |
| 6021 | - return str.replace(/^\s*/, '').replace(/\s*$/, ''); | |
| 6006 | + return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, ''); | |
| 6022 | 6007 | } |
| 6023 | 6008 | |
| 6024 | 6009 | /** |
| ... | ... | @@ -6156,6 +6141,94 @@ var ZLMRTCClient = (function (exports) { |
| 6156 | 6141 | return content; |
| 6157 | 6142 | } |
| 6158 | 6143 | |
| 6144 | + /** | |
| 6145 | + * Inherit the prototype methods from one constructor into another | |
| 6146 | + * @param {function} constructor | |
| 6147 | + * @param {function} superConstructor | |
| 6148 | + * @param {object} [props] | |
| 6149 | + * @param {object} [descriptors] | |
| 6150 | + */ | |
| 6151 | + | |
| 6152 | + function inherits(constructor, superConstructor, props, descriptors) { | |
| 6153 | + constructor.prototype = Object.create(superConstructor.prototype, descriptors); | |
| 6154 | + constructor.prototype.constructor = constructor; | |
| 6155 | + props && Object.assign(constructor.prototype, props); | |
| 6156 | + } | |
| 6157 | + | |
| 6158 | + /** | |
| 6159 | + * Resolve object with deep prototype chain to a flat object | |
| 6160 | + * @param {Object} sourceObj source object | |
| 6161 | + * @param {Object} [destObj] | |
| 6162 | + * @param {Function} [filter] | |
| 6163 | + * @returns {Object} | |
| 6164 | + */ | |
| 6165 | + | |
| 6166 | + function toFlatObject(sourceObj, destObj, filter) { | |
| 6167 | + var props; | |
| 6168 | + var i; | |
| 6169 | + var prop; | |
| 6170 | + var merged = {}; | |
| 6171 | + | |
| 6172 | + destObj = destObj || {}; | |
| 6173 | + | |
| 6174 | + do { | |
| 6175 | + props = Object.getOwnPropertyNames(sourceObj); | |
| 6176 | + i = props.length; | |
| 6177 | + while (i-- > 0) { | |
| 6178 | + prop = props[i]; | |
| 6179 | + if (!merged[prop]) { | |
| 6180 | + destObj[prop] = sourceObj[prop]; | |
| 6181 | + merged[prop] = true; | |
| 6182 | + } | |
| 6183 | + } | |
| 6184 | + sourceObj = Object.getPrototypeOf(sourceObj); | |
| 6185 | + } while (sourceObj && (!filter || filter(sourceObj, destObj)) && sourceObj !== Object.prototype); | |
| 6186 | + | |
| 6187 | + return destObj; | |
| 6188 | + } | |
| 6189 | + | |
| 6190 | + /* | |
| 6191 | + * determines whether a string ends with the characters of a specified string | |
| 6192 | + * @param {String} str | |
| 6193 | + * @param {String} searchString | |
| 6194 | + * @param {Number} [position= 0] | |
| 6195 | + * @returns {boolean} | |
| 6196 | + */ | |
| 6197 | + function endsWith(str, searchString, position) { | |
| 6198 | + str = String(str); | |
| 6199 | + if (position === undefined || position > str.length) { | |
| 6200 | + position = str.length; | |
| 6201 | + } | |
| 6202 | + position -= searchString.length; | |
| 6203 | + var lastIndex = str.indexOf(searchString, position); | |
| 6204 | + return lastIndex !== -1 && lastIndex === position; | |
| 6205 | + } | |
| 6206 | + | |
| 6207 | + | |
| 6208 | + /** | |
| 6209 | + * Returns new array from array like object | |
| 6210 | + * @param {*} [thing] | |
| 6211 | + * @returns {Array} | |
| 6212 | + */ | |
| 6213 | + function toArray(thing) { | |
| 6214 | + if (!thing) return null; | |
| 6215 | + var i = thing.length; | |
| 6216 | + if (isUndefined(i)) return null; | |
| 6217 | + var arr = new Array(i); | |
| 6218 | + while (i-- > 0) { | |
| 6219 | + arr[i] = thing[i]; | |
| 6220 | + } | |
| 6221 | + return arr; | |
| 6222 | + } | |
| 6223 | + | |
| 6224 | + // eslint-disable-next-line func-names | |
| 6225 | + var isTypedArray = (function(TypedArray) { | |
| 6226 | + // eslint-disable-next-line func-names | |
| 6227 | + return function(thing) { | |
| 6228 | + return TypedArray && thing instanceof TypedArray; | |
| 6229 | + }; | |
| 6230 | + })(typeof Uint8Array !== 'undefined' && Object.getPrototypeOf(Uint8Array)); | |
| 6231 | + | |
| 6159 | 6232 | var utils = { |
| 6160 | 6233 | isArray: isArray, |
| 6161 | 6234 | isArrayBuffer: isArrayBuffer, |
| ... | ... | @@ -6178,7 +6251,15 @@ var ZLMRTCClient = (function (exports) { |
| 6178 | 6251 | merge: merge, |
| 6179 | 6252 | extend: extend, |
| 6180 | 6253 | trim: trim, |
| 6181 | - stripBOM: stripBOM | |
| 6254 | + stripBOM: stripBOM, | |
| 6255 | + inherits: inherits, | |
| 6256 | + toFlatObject: toFlatObject, | |
| 6257 | + kindOf: kindOf, | |
| 6258 | + kindOfTest: kindOfTest, | |
| 6259 | + endsWith: endsWith, | |
| 6260 | + toArray: toArray, | |
| 6261 | + isTypedArray: isTypedArray, | |
| 6262 | + isFileList: isFileList | |
| 6182 | 6263 | }; |
| 6183 | 6264 | |
| 6184 | 6265 | function encode(val) { |
| ... | ... | @@ -6260,10 +6341,12 @@ var ZLMRTCClient = (function (exports) { |
| 6260 | 6341 | * |
| 6261 | 6342 | * @return {Number} An ID used to remove interceptor later |
| 6262 | 6343 | */ |
| 6263 | - InterceptorManager.prototype.use = function use(fulfilled, rejected) { | |
| 6344 | + InterceptorManager.prototype.use = function use(fulfilled, rejected, options) { | |
| 6264 | 6345 | this.handlers.push({ |
| 6265 | 6346 | fulfilled: fulfilled, |
| 6266 | - rejected: rejected | |
| 6347 | + rejected: rejected, | |
| 6348 | + synchronous: options ? options.synchronous : false, | |
| 6349 | + runWhen: options ? options.runWhen : null | |
| 6267 | 6350 | }); |
| 6268 | 6351 | return this.handlers.length - 1; |
| 6269 | 6352 | }; |
| ... | ... | @@ -6297,27 +6380,6 @@ var ZLMRTCClient = (function (exports) { |
| 6297 | 6380 | |
| 6298 | 6381 | var InterceptorManager_1 = InterceptorManager; |
| 6299 | 6382 | |
| 6300 | - /** | |
| 6301 | - * Transform the data for a request or a response | |
| 6302 | - * | |
| 6303 | - * @param {Object|String} data The data to be transformed | |
| 6304 | - * @param {Array} headers The headers for the request or response | |
| 6305 | - * @param {Array|Function} fns A single function or Array of functions | |
| 6306 | - * @returns {*} The resulting transformed data | |
| 6307 | - */ | |
| 6308 | - var transformData = function transformData(data, headers, fns) { | |
| 6309 | - /*eslint no-param-reassign:0*/ | |
| 6310 | - utils.forEach(fns, function transform(fn) { | |
| 6311 | - data = fn(data, headers); | |
| 6312 | - }); | |
| 6313 | - | |
| 6314 | - return data; | |
| 6315 | - }; | |
| 6316 | - | |
| 6317 | - var isCancel = function isCancel(value) { | |
| 6318 | - return !!(value && value.__CANCEL__); | |
| 6319 | - }; | |
| 6320 | - | |
| 6321 | 6383 | var normalizeHeaderName = function normalizeHeaderName(headers, normalizedName) { |
| 6322 | 6384 | utils.forEach(headers, function processHeader(value, name) { |
| 6323 | 6385 | if (name !== normalizedName && name.toUpperCase() === normalizedName.toUpperCase()) { |
| ... | ... | @@ -6328,26 +6390,27 @@ var ZLMRTCClient = (function (exports) { |
| 6328 | 6390 | }; |
| 6329 | 6391 | |
| 6330 | 6392 | /** |
| 6331 | - * Update an Error with the specified config, error code, and response. | |
| 6393 | + * Create an Error with the specified message, config, error code, request and response. | |
| 6332 | 6394 | * |
| 6333 | - * @param {Error} error The error to update. | |
| 6334 | - * @param {Object} config The config. | |
| 6395 | + * @param {string} message The error message. | |
| 6335 | 6396 | * @param {string} [code] The error code (for example, 'ECONNABORTED'). |
| 6397 | + * @param {Object} [config] The config. | |
| 6336 | 6398 | * @param {Object} [request] The request. |
| 6337 | 6399 | * @param {Object} [response] The response. |
| 6338 | - * @returns {Error} The error. | |
| 6400 | + * @returns {Error} The created error. | |
| 6339 | 6401 | */ |
| 6340 | - var enhanceError = function enhanceError(error, config, code, request, response) { | |
| 6341 | - error.config = config; | |
| 6342 | - if (code) { | |
| 6343 | - error.code = code; | |
| 6344 | - } | |
| 6345 | - | |
| 6346 | - error.request = request; | |
| 6347 | - error.response = response; | |
| 6348 | - error.isAxiosError = true; | |
| 6402 | + function AxiosError(message, code, config, request, response) { | |
| 6403 | + Error.call(this); | |
| 6404 | + this.message = message; | |
| 6405 | + this.name = 'AxiosError'; | |
| 6406 | + code && (this.code = code); | |
| 6407 | + config && (this.config = config); | |
| 6408 | + request && (this.request = request); | |
| 6409 | + response && (this.response = response); | |
| 6410 | + } | |
| 6349 | 6411 | |
| 6350 | - error.toJSON = function toJSON() { | |
| 6412 | + utils.inherits(AxiosError, Error, { | |
| 6413 | + toJSON: function toJSON() { | |
| 6351 | 6414 | return { |
| 6352 | 6415 | // Standard |
| 6353 | 6416 | message: this.message, |
| ... | ... | @@ -6362,28 +6425,129 @@ var ZLMRTCClient = (function (exports) { |
| 6362 | 6425 | stack: this.stack, |
| 6363 | 6426 | // Axios |
| 6364 | 6427 | config: this.config, |
| 6365 | - code: this.code | |
| 6428 | + code: this.code, | |
| 6429 | + status: this.response && this.response.status ? this.response.status : null | |
| 6366 | 6430 | }; |
| 6367 | - }; | |
| 6368 | - return error; | |
| 6431 | + } | |
| 6432 | + }); | |
| 6433 | + | |
| 6434 | + var prototype = AxiosError.prototype; | |
| 6435 | + var descriptors = {}; | |
| 6436 | + | |
| 6437 | + [ | |
| 6438 | + 'ERR_BAD_OPTION_VALUE', | |
| 6439 | + 'ERR_BAD_OPTION', | |
| 6440 | + 'ECONNABORTED', | |
| 6441 | + 'ETIMEDOUT', | |
| 6442 | + 'ERR_NETWORK', | |
| 6443 | + 'ERR_FR_TOO_MANY_REDIRECTS', | |
| 6444 | + 'ERR_DEPRECATED', | |
| 6445 | + 'ERR_BAD_RESPONSE', | |
| 6446 | + 'ERR_BAD_REQUEST', | |
| 6447 | + 'ERR_CANCELED' | |
| 6448 | + // eslint-disable-next-line func-names | |
| 6449 | + ].forEach(function(code) { | |
| 6450 | + descriptors[code] = {value: code}; | |
| 6451 | + }); | |
| 6452 | + | |
| 6453 | + Object.defineProperties(AxiosError, descriptors); | |
| 6454 | + Object.defineProperty(prototype, 'isAxiosError', {value: true}); | |
| 6455 | + | |
| 6456 | + // eslint-disable-next-line func-names | |
| 6457 | + AxiosError.from = function(error, code, config, request, response, customProps) { | |
| 6458 | + var axiosError = Object.create(prototype); | |
| 6459 | + | |
| 6460 | + utils.toFlatObject(error, axiosError, function filter(obj) { | |
| 6461 | + return obj !== Error.prototype; | |
| 6462 | + }); | |
| 6463 | + | |
| 6464 | + AxiosError.call(axiosError, error.message, code, config, request, response); | |
| 6465 | + | |
| 6466 | + axiosError.name = error.name; | |
| 6467 | + | |
| 6468 | + customProps && Object.assign(axiosError, customProps); | |
| 6469 | + | |
| 6470 | + return axiosError; | |
| 6369 | 6471 | }; |
| 6370 | 6472 | |
| 6371 | - /** | |
| 6372 | - * Create an Error with the specified message, config, error code, request and response. | |
| 6373 | - * | |
| 6374 | - * @param {string} message The error message. | |
| 6375 | - * @param {Object} config The config. | |
| 6376 | - * @param {string} [code] The error code (for example, 'ECONNABORTED'). | |
| 6377 | - * @param {Object} [request] The request. | |
| 6378 | - * @param {Object} [response] The response. | |
| 6379 | - * @returns {Error} The created error. | |
| 6380 | - */ | |
| 6381 | - var createError = function createError(message, config, code, request, response) { | |
| 6382 | - var error = new Error(message); | |
| 6383 | - return enhanceError(error, config, code, request, response); | |
| 6473 | + var AxiosError_1 = AxiosError; | |
| 6474 | + | |
| 6475 | + var transitional = { | |
| 6476 | + silentJSONParsing: true, | |
| 6477 | + forcedJSONParsing: true, | |
| 6478 | + clarifyTimeoutError: false | |
| 6384 | 6479 | }; |
| 6385 | 6480 | |
| 6386 | 6481 | /** |
| 6482 | + * Convert a data object to FormData | |
| 6483 | + * @param {Object} obj | |
| 6484 | + * @param {?Object} [formData] | |
| 6485 | + * @returns {Object} | |
| 6486 | + **/ | |
| 6487 | + | |
| 6488 | + function toFormData(obj, formData) { | |
| 6489 | + // eslint-disable-next-line no-param-reassign | |
| 6490 | + formData = formData || new FormData(); | |
| 6491 | + | |
| 6492 | + var stack = []; | |
| 6493 | + | |
| 6494 | + function convertValue(value) { | |
| 6495 | + if (value === null) return ''; | |
| 6496 | + | |
| 6497 | + if (utils.isDate(value)) { | |
| 6498 | + return value.toISOString(); | |
| 6499 | + } | |
| 6500 | + | |
| 6501 | + if (utils.isArrayBuffer(value) || utils.isTypedArray(value)) { | |
| 6502 | + return typeof Blob === 'function' ? new Blob([value]) : Buffer.from(value); | |
| 6503 | + } | |
| 6504 | + | |
| 6505 | + return value; | |
| 6506 | + } | |
| 6507 | + | |
| 6508 | + function build(data, parentKey) { | |
| 6509 | + if (utils.isPlainObject(data) || utils.isArray(data)) { | |
| 6510 | + if (stack.indexOf(data) !== -1) { | |
| 6511 | + throw Error('Circular reference detected in ' + parentKey); | |
| 6512 | + } | |
| 6513 | + | |
| 6514 | + stack.push(data); | |
| 6515 | + | |
| 6516 | + utils.forEach(data, function each(value, key) { | |
| 6517 | + if (utils.isUndefined(value)) return; | |
| 6518 | + var fullKey = parentKey ? parentKey + '.' + key : key; | |
| 6519 | + var arr; | |
| 6520 | + | |
| 6521 | + if (value && !parentKey && typeof value === 'object') { | |
| 6522 | + if (utils.endsWith(key, '{}')) { | |
| 6523 | + // eslint-disable-next-line no-param-reassign | |
| 6524 | + value = JSON.stringify(value); | |
| 6525 | + } else if (utils.endsWith(key, '[]') && (arr = utils.toArray(value))) { | |
| 6526 | + // eslint-disable-next-line func-names | |
| 6527 | + arr.forEach(function(el) { | |
| 6528 | + !utils.isUndefined(el) && formData.append(fullKey, convertValue(el)); | |
| 6529 | + }); | |
| 6530 | + return; | |
| 6531 | + } | |
| 6532 | + } | |
| 6533 | + | |
| 6534 | + build(value, fullKey); | |
| 6535 | + }); | |
| 6536 | + | |
| 6537 | + stack.pop(); | |
| 6538 | + } else { | |
| 6539 | + formData.append(parentKey, convertValue(data)); | |
| 6540 | + } | |
| 6541 | + } | |
| 6542 | + | |
| 6543 | + build(obj); | |
| 6544 | + | |
| 6545 | + return formData; | |
| 6546 | + } | |
| 6547 | + | |
| 6548 | + var toFormData_1 = toFormData; | |
| 6549 | + | |
| 6550 | + /** | |
| 6387 | 6551 | * Resolve or reject a Promise based on response status. |
| 6388 | 6552 | * |
| 6389 | 6553 | * @param {Function} resolve A function that resolves the promise. |
| ... | ... | @@ -6395,10 +6559,10 @@ var ZLMRTCClient = (function (exports) { |
| 6395 | 6559 | if (!response.status || !validateStatus || validateStatus(response.status)) { |
| 6396 | 6560 | resolve(response); |
| 6397 | 6561 | } else { |
| 6398 | - reject(createError( | |
| 6562 | + reject(new AxiosError_1( | |
| 6399 | 6563 | 'Request failed with status code ' + response.status, |
| 6564 | + [AxiosError_1.ERR_BAD_REQUEST, AxiosError_1.ERR_BAD_RESPONSE][Math.floor(response.status / 100) - 4], | |
| 6400 | 6565 | response.config, |
| 6401 | - null, | |
| 6402 | 6566 | response.request, |
| 6403 | 6567 | response |
| 6404 | 6568 | )); |
| ... | ... | @@ -6465,7 +6629,7 @@ var ZLMRTCClient = (function (exports) { |
| 6465 | 6629 | // A URL is considered absolute if it begins with "<scheme>://" or "//" (protocol-relative URL). |
| 6466 | 6630 | // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed |
| 6467 | 6631 | // by any combination of letters, digits, plus, period, or hyphen. |
| 6468 | - return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url); | |
| 6632 | + return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url); | |
| 6469 | 6633 | }; |
| 6470 | 6634 | |
| 6471 | 6635 | /** |
| ... | ... | @@ -6612,12 +6776,46 @@ var ZLMRTCClient = (function (exports) { |
| 6612 | 6776 | })() |
| 6613 | 6777 | ); |
| 6614 | 6778 | |
| 6779 | + /** | |
| 6780 | + * A `CanceledError` is an object that is thrown when an operation is canceled. | |
| 6781 | + * | |
| 6782 | + * @class | |
| 6783 | + * @param {string=} message The message. | |
| 6784 | + */ | |
| 6785 | + function CanceledError(message) { | |
| 6786 | + // eslint-disable-next-line no-eq-null,eqeqeq | |
| 6787 | + AxiosError_1.call(this, message == null ? 'canceled' : message, AxiosError_1.ERR_CANCELED); | |
| 6788 | + this.name = 'CanceledError'; | |
| 6789 | + } | |
| 6790 | + | |
| 6791 | + utils.inherits(CanceledError, AxiosError_1, { | |
| 6792 | + __CANCEL__: true | |
| 6793 | + }); | |
| 6794 | + | |
| 6795 | + var CanceledError_1 = CanceledError; | |
| 6796 | + | |
| 6797 | + var parseProtocol = function parseProtocol(url) { | |
| 6798 | + var match = /^([-+\w]{1,25})(:?\/\/|:)/.exec(url); | |
| 6799 | + return match && match[1] || ''; | |
| 6800 | + }; | |
| 6801 | + | |
| 6615 | 6802 | var xhr = function xhrAdapter(config) { |
| 6616 | 6803 | return new Promise(function dispatchXhrRequest(resolve, reject) { |
| 6617 | 6804 | var requestData = config.data; |
| 6618 | 6805 | var requestHeaders = config.headers; |
| 6806 | + var responseType = config.responseType; | |
| 6807 | + var onCanceled; | |
| 6808 | + function done() { | |
| 6809 | + if (config.cancelToken) { | |
| 6810 | + config.cancelToken.unsubscribe(onCanceled); | |
| 6811 | + } | |
| 6619 | 6812 | |
| 6620 | - if (utils.isFormData(requestData)) { | |
| 6813 | + if (config.signal) { | |
| 6814 | + config.signal.removeEventListener('abort', onCanceled); | |
| 6815 | + } | |
| 6816 | + } | |
| 6817 | + | |
| 6818 | + if (utils.isFormData(requestData) && utils.isStandardBrowserEnv()) { | |
| 6621 | 6819 | delete requestHeaders['Content-Type']; // Let the browser set it |
| 6622 | 6820 | } |
| 6623 | 6821 | |
| ... | ... | @@ -6631,28 +6829,20 @@ var ZLMRTCClient = (function (exports) { |
| 6631 | 6829 | } |
| 6632 | 6830 | |
| 6633 | 6831 | var fullPath = buildFullPath(config.baseURL, config.url); |
| 6832 | + | |
| 6634 | 6833 | request.open(config.method.toUpperCase(), buildURL(fullPath, config.params, config.paramsSerializer), true); |
| 6635 | 6834 | |
| 6636 | 6835 | // Set the request timeout in MS |
| 6637 | 6836 | request.timeout = config.timeout; |
| 6638 | 6837 | |
| 6639 | - // Listen for ready state | |
| 6640 | - request.onreadystatechange = function handleLoad() { | |
| 6641 | - if (!request || request.readyState !== 4) { | |
| 6642 | - return; | |
| 6643 | - } | |
| 6644 | - | |
| 6645 | - // The request errored out and we didn't get a response, this will be | |
| 6646 | - // handled by onerror instead | |
| 6647 | - // With one exception: request that using file: protocol, most browsers | |
| 6648 | - // will return status as 0 even though it's a successful request | |
| 6649 | - if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) { | |
| 6838 | + function onloadend() { | |
| 6839 | + if (!request) { | |
| 6650 | 6840 | return; |
| 6651 | 6841 | } |
| 6652 | - | |
| 6653 | 6842 | // Prepare the response |
| 6654 | 6843 | var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null; |
| 6655 | - var responseData = !config.responseType || config.responseType === 'text' ? request.responseText : request.response; | |
| 6844 | + var responseData = !responseType || responseType === 'text' || responseType === 'json' ? | |
| 6845 | + request.responseText : request.response; | |
| 6656 | 6846 | var response = { |
| 6657 | 6847 | data: responseData, |
| 6658 | 6848 | status: request.status, |
| ... | ... | @@ -6662,11 +6852,40 @@ var ZLMRTCClient = (function (exports) { |
| 6662 | 6852 | request: request |
| 6663 | 6853 | }; |
| 6664 | 6854 | |
| 6665 | - settle(resolve, reject, response); | |
| 6855 | + settle(function _resolve(value) { | |
| 6856 | + resolve(value); | |
| 6857 | + done(); | |
| 6858 | + }, function _reject(err) { | |
| 6859 | + reject(err); | |
| 6860 | + done(); | |
| 6861 | + }, response); | |
| 6666 | 6862 | |
| 6667 | 6863 | // Clean up request |
| 6668 | 6864 | request = null; |
| 6669 | - }; | |
| 6865 | + } | |
| 6866 | + | |
| 6867 | + if ('onloadend' in request) { | |
| 6868 | + // Use onloadend if available | |
| 6869 | + request.onloadend = onloadend; | |
| 6870 | + } else { | |
| 6871 | + // Listen for ready state to emulate onloadend | |
| 6872 | + request.onreadystatechange = function handleLoad() { | |
| 6873 | + if (!request || request.readyState !== 4) { | |
| 6874 | + return; | |
| 6875 | + } | |
| 6876 | + | |
| 6877 | + // The request errored out and we didn't get a response, this will be | |
| 6878 | + // handled by onerror instead | |
| 6879 | + // With one exception: request that using file: protocol, most browsers | |
| 6880 | + // will return status as 0 even though it's a successful request | |
| 6881 | + if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) { | |
| 6882 | + return; | |
| 6883 | + } | |
| 6884 | + // readystate handler is calling before onerror or ontimeout handlers, | |
| 6885 | + // so we should call onloadend on the next 'tick' | |
| 6886 | + setTimeout(onloadend); | |
| 6887 | + }; | |
| 6888 | + } | |
| 6670 | 6889 | |
| 6671 | 6890 | // Handle browser request cancellation (as opposed to a manual cancellation) |
| 6672 | 6891 | request.onabort = function handleAbort() { |
| ... | ... | @@ -6674,7 +6893,7 @@ var ZLMRTCClient = (function (exports) { |
| 6674 | 6893 | return; |
| 6675 | 6894 | } |
| 6676 | 6895 | |
| 6677 | - reject(createError('Request aborted', config, 'ECONNABORTED', request)); | |
| 6896 | + reject(new AxiosError_1('Request aborted', AxiosError_1.ECONNABORTED, config, request)); | |
| 6678 | 6897 | |
| 6679 | 6898 | // Clean up request |
| 6680 | 6899 | request = null; |
| ... | ... | @@ -6684,7 +6903,7 @@ var ZLMRTCClient = (function (exports) { |
| 6684 | 6903 | request.onerror = function handleError() { |
| 6685 | 6904 | // Real errors are hidden from us by the browser |
| 6686 | 6905 | // onerror should only fire if it's a network error |
| 6687 | - reject(createError('Network Error', config, null, request)); | |
| 6906 | + reject(new AxiosError_1('Network Error', AxiosError_1.ERR_NETWORK, config, request, request)); | |
| 6688 | 6907 | |
| 6689 | 6908 | // Clean up request |
| 6690 | 6909 | request = null; |
| ... | ... | @@ -6692,11 +6911,15 @@ var ZLMRTCClient = (function (exports) { |
| 6692 | 6911 | |
| 6693 | 6912 | // Handle timeout |
| 6694 | 6913 | request.ontimeout = function handleTimeout() { |
| 6695 | - var timeoutErrorMessage = 'timeout of ' + config.timeout + 'ms exceeded'; | |
| 6914 | + var timeoutErrorMessage = config.timeout ? 'timeout of ' + config.timeout + 'ms exceeded' : 'timeout exceeded'; | |
| 6915 | + var transitional$1 = config.transitional || transitional; | |
| 6696 | 6916 | if (config.timeoutErrorMessage) { |
| 6697 | 6917 | timeoutErrorMessage = config.timeoutErrorMessage; |
| 6698 | 6918 | } |
| 6699 | - reject(createError(timeoutErrorMessage, config, 'ECONNABORTED', | |
| 6919 | + reject(new AxiosError_1( | |
| 6920 | + timeoutErrorMessage, | |
| 6921 | + transitional$1.clarifyTimeoutError ? AxiosError_1.ETIMEDOUT : AxiosError_1.ECONNABORTED, | |
| 6922 | + config, | |
| 6700 | 6923 | request)); |
| 6701 | 6924 | |
| 6702 | 6925 | // Clean up request |
| ... | ... | @@ -6736,16 +6959,8 @@ var ZLMRTCClient = (function (exports) { |
| 6736 | 6959 | } |
| 6737 | 6960 | |
| 6738 | 6961 | // Add responseType to request if needed |
| 6739 | - if (config.responseType) { | |
| 6740 | - try { | |
| 6741 | - request.responseType = config.responseType; | |
| 6742 | - } catch (e) { | |
| 6743 | - // Expected DOMException thrown by browsers not compatible XMLHttpRequest Level 2. | |
| 6744 | - // But, this can be suppressed for 'json' type as it can be parsed by default 'transformResponse' function. | |
| 6745 | - if (config.responseType !== 'json') { | |
| 6746 | - throw e; | |
| 6747 | - } | |
| 6748 | - } | |
| 6962 | + if (responseType && responseType !== 'json') { | |
| 6963 | + request.responseType = config.responseType; | |
| 6749 | 6964 | } |
| 6750 | 6965 | |
| 6751 | 6966 | // Handle progress if needed |
| ... | ... | @@ -6758,29 +6973,44 @@ var ZLMRTCClient = (function (exports) { |
| 6758 | 6973 | request.upload.addEventListener('progress', config.onUploadProgress); |
| 6759 | 6974 | } |
| 6760 | 6975 | |
| 6761 | - if (config.cancelToken) { | |
| 6976 | + if (config.cancelToken || config.signal) { | |
| 6762 | 6977 | // Handle cancellation |
| 6763 | - config.cancelToken.promise.then(function onCanceled(cancel) { | |
| 6978 | + // eslint-disable-next-line func-names | |
| 6979 | + onCanceled = function(cancel) { | |
| 6764 | 6980 | if (!request) { |
| 6765 | 6981 | return; |
| 6766 | 6982 | } |
| 6767 | - | |
| 6983 | + reject(!cancel || (cancel && cancel.type) ? new CanceledError_1() : cancel); | |
| 6768 | 6984 | request.abort(); |
| 6769 | - reject(cancel); | |
| 6770 | - // Clean up request | |
| 6771 | 6985 | request = null; |
| 6772 | - }); | |
| 6986 | + }; | |
| 6987 | + | |
| 6988 | + config.cancelToken && config.cancelToken.subscribe(onCanceled); | |
| 6989 | + if (config.signal) { | |
| 6990 | + config.signal.aborted ? onCanceled() : config.signal.addEventListener('abort', onCanceled); | |
| 6991 | + } | |
| 6773 | 6992 | } |
| 6774 | 6993 | |
| 6775 | 6994 | if (!requestData) { |
| 6776 | 6995 | requestData = null; |
| 6777 | 6996 | } |
| 6778 | 6997 | |
| 6998 | + var protocol = parseProtocol(fullPath); | |
| 6999 | + | |
| 7000 | + if (protocol && [ 'http', 'https', 'file' ].indexOf(protocol) === -1) { | |
| 7001 | + reject(new AxiosError_1('Unsupported protocol ' + protocol + ':', AxiosError_1.ERR_BAD_REQUEST, config)); | |
| 7002 | + return; | |
| 7003 | + } | |
| 7004 | + | |
| 7005 | + | |
| 6779 | 7006 | // Send the request |
| 6780 | 7007 | request.send(requestData); |
| 6781 | 7008 | }); |
| 6782 | 7009 | }; |
| 6783 | 7010 | |
| 7011 | + // eslint-disable-next-line strict | |
| 7012 | + var _null = null; | |
| 7013 | + | |
| 6784 | 7014 | var DEFAULT_CONTENT_TYPE = { |
| 6785 | 7015 | 'Content-Type': 'application/x-www-form-urlencoded' |
| 6786 | 7016 | }; |
| ... | ... | @@ -6803,12 +7033,31 @@ var ZLMRTCClient = (function (exports) { |
| 6803 | 7033 | return adapter; |
| 6804 | 7034 | } |
| 6805 | 7035 | |
| 7036 | + function stringifySafely(rawValue, parser, encoder) { | |
| 7037 | + if (utils.isString(rawValue)) { | |
| 7038 | + try { | |
| 7039 | + (parser || JSON.parse)(rawValue); | |
| 7040 | + return utils.trim(rawValue); | |
| 7041 | + } catch (e) { | |
| 7042 | + if (e.name !== 'SyntaxError') { | |
| 7043 | + throw e; | |
| 7044 | + } | |
| 7045 | + } | |
| 7046 | + } | |
| 7047 | + | |
| 7048 | + return (encoder || JSON.stringify)(rawValue); | |
| 7049 | + } | |
| 7050 | + | |
| 6806 | 7051 | var defaults = { |
| 7052 | + | |
| 7053 | + transitional: transitional, | |
| 7054 | + | |
| 6807 | 7055 | adapter: getDefaultAdapter(), |
| 6808 | 7056 | |
| 6809 | 7057 | transformRequest: [function transformRequest(data, headers) { |
| 6810 | 7058 | normalizeHeaderName(headers, 'Accept'); |
| 6811 | 7059 | normalizeHeaderName(headers, 'Content-Type'); |
| 7060 | + | |
| 6812 | 7061 | if (utils.isFormData(data) || |
| 6813 | 7062 | utils.isArrayBuffer(data) || |
| 6814 | 7063 | utils.isBuffer(data) || |
| ... | ... | @@ -6825,20 +7074,42 @@ var ZLMRTCClient = (function (exports) { |
| 6825 | 7074 | setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8'); |
| 6826 | 7075 | return data.toString(); |
| 6827 | 7076 | } |
| 6828 | - if (utils.isObject(data)) { | |
| 6829 | - setContentTypeIfUnset(headers, 'application/json;charset=utf-8'); | |
| 6830 | - return JSON.stringify(data); | |
| 7077 | + | |
| 7078 | + var isObjectPayload = utils.isObject(data); | |
| 7079 | + var contentType = headers && headers['Content-Type']; | |
| 7080 | + | |
| 7081 | + var isFileList; | |
| 7082 | + | |
| 7083 | + if ((isFileList = utils.isFileList(data)) || (isObjectPayload && contentType === 'multipart/form-data')) { | |
| 7084 | + var _FormData = this.env && this.env.FormData; | |
| 7085 | + return toFormData_1(isFileList ? {'files[]': data} : data, _FormData && new _FormData()); | |
| 7086 | + } else if (isObjectPayload || contentType === 'application/json') { | |
| 7087 | + setContentTypeIfUnset(headers, 'application/json'); | |
| 7088 | + return stringifySafely(data); | |
| 6831 | 7089 | } |
| 7090 | + | |
| 6832 | 7091 | return data; |
| 6833 | 7092 | }], |
| 6834 | 7093 | |
| 6835 | 7094 | transformResponse: [function transformResponse(data) { |
| 6836 | - /*eslint no-param-reassign:0*/ | |
| 6837 | - if (typeof data === 'string') { | |
| 7095 | + var transitional = this.transitional || defaults.transitional; | |
| 7096 | + var silentJSONParsing = transitional && transitional.silentJSONParsing; | |
| 7097 | + var forcedJSONParsing = transitional && transitional.forcedJSONParsing; | |
| 7098 | + var strictJSONParsing = !silentJSONParsing && this.responseType === 'json'; | |
| 7099 | + | |
| 7100 | + if (strictJSONParsing || (forcedJSONParsing && utils.isString(data) && data.length)) { | |
| 6838 | 7101 | try { |
| 6839 | - data = JSON.parse(data); | |
| 6840 | - } catch (e) { /* Ignore */ } | |
| 7102 | + return JSON.parse(data); | |
| 7103 | + } catch (e) { | |
| 7104 | + if (strictJSONParsing) { | |
| 7105 | + if (e.name === 'SyntaxError') { | |
| 7106 | + throw AxiosError_1.from(e, AxiosError_1.ERR_BAD_RESPONSE, this, null, this.response); | |
| 7107 | + } | |
| 7108 | + throw e; | |
| 7109 | + } | |
| 7110 | + } | |
| 6841 | 7111 | } |
| 7112 | + | |
| 6842 | 7113 | return data; |
| 6843 | 7114 | }], |
| 6844 | 7115 | |
| ... | ... | @@ -6854,14 +7125,18 @@ var ZLMRTCClient = (function (exports) { |
| 6854 | 7125 | maxContentLength: -1, |
| 6855 | 7126 | maxBodyLength: -1, |
| 6856 | 7127 | |
| 7128 | + env: { | |
| 7129 | + FormData: _null | |
| 7130 | + }, | |
| 7131 | + | |
| 6857 | 7132 | validateStatus: function validateStatus(status) { |
| 6858 | 7133 | return status >= 200 && status < 300; |
| 6859 | - } | |
| 6860 | - }; | |
| 7134 | + }, | |
| 6861 | 7135 | |
| 6862 | - defaults.headers = { | |
| 6863 | - common: { | |
| 6864 | - 'Accept': 'application/json, text/plain, */*' | |
| 7136 | + headers: { | |
| 7137 | + common: { | |
| 7138 | + 'Accept': 'application/json, text/plain, */*' | |
| 7139 | + } | |
| 6865 | 7140 | } |
| 6866 | 7141 | }; |
| 6867 | 7142 | |
| ... | ... | @@ -6876,12 +7151,38 @@ var ZLMRTCClient = (function (exports) { |
| 6876 | 7151 | var defaults_1 = defaults; |
| 6877 | 7152 | |
| 6878 | 7153 | /** |
| 6879 | - * Throws a `Cancel` if cancellation has been requested. | |
| 7154 | + * Transform the data for a request or a response | |
| 7155 | + * | |
| 7156 | + * @param {Object|String} data The data to be transformed | |
| 7157 | + * @param {Array} headers The headers for the request or response | |
| 7158 | + * @param {Array|Function} fns A single function or Array of functions | |
| 7159 | + * @returns {*} The resulting transformed data | |
| 7160 | + */ | |
| 7161 | + var transformData = function transformData(data, headers, fns) { | |
| 7162 | + var context = this || defaults_1; | |
| 7163 | + /*eslint no-param-reassign:0*/ | |
| 7164 | + utils.forEach(fns, function transform(fn) { | |
| 7165 | + data = fn.call(context, data, headers); | |
| 7166 | + }); | |
| 7167 | + | |
| 7168 | + return data; | |
| 7169 | + }; | |
| 7170 | + | |
| 7171 | + var isCancel = function isCancel(value) { | |
| 7172 | + return !!(value && value.__CANCEL__); | |
| 7173 | + }; | |
| 7174 | + | |
| 7175 | + /** | |
| 7176 | + * Throws a `CanceledError` if cancellation has been requested. | |
| 6880 | 7177 | */ |
| 6881 | 7178 | function throwIfCancellationRequested(config) { |
| 6882 | 7179 | if (config.cancelToken) { |
| 6883 | 7180 | config.cancelToken.throwIfRequested(); |
| 6884 | 7181 | } |
| 7182 | + | |
| 7183 | + if (config.signal && config.signal.aborted) { | |
| 7184 | + throw new CanceledError_1(); | |
| 7185 | + } | |
| 6885 | 7186 | } |
| 6886 | 7187 | |
| 6887 | 7188 | /** |
| ... | ... | @@ -6897,7 +7198,8 @@ var ZLMRTCClient = (function (exports) { |
| 6897 | 7198 | config.headers = config.headers || {}; |
| 6898 | 7199 | |
| 6899 | 7200 | // Transform request data |
| 6900 | - config.data = transformData( | |
| 7201 | + config.data = transformData.call( | |
| 7202 | + config, | |
| 6901 | 7203 | config.data, |
| 6902 | 7204 | config.headers, |
| 6903 | 7205 | config.transformRequest |
| ... | ... | @@ -6923,7 +7225,8 @@ var ZLMRTCClient = (function (exports) { |
| 6923 | 7225 | throwIfCancellationRequested(config); |
| 6924 | 7226 | |
| 6925 | 7227 | // Transform response data |
| 6926 | - response.data = transformData( | |
| 7228 | + response.data = transformData.call( | |
| 7229 | + config, | |
| 6927 | 7230 | response.data, |
| 6928 | 7231 | response.headers, |
| 6929 | 7232 | config.transformResponse |
| ... | ... | @@ -6936,7 +7239,8 @@ var ZLMRTCClient = (function (exports) { |
| 6936 | 7239 | |
| 6937 | 7240 | // Transform response data |
| 6938 | 7241 | if (reason && reason.response) { |
| 6939 | - reason.response.data = transformData( | |
| 7242 | + reason.response.data = transformData.call( | |
| 7243 | + config, | |
| 6940 | 7244 | reason.response.data, |
| 6941 | 7245 | reason.response.headers, |
| 6942 | 7246 | config.transformResponse |
| ... | ... | @@ -6961,17 +7265,6 @@ var ZLMRTCClient = (function (exports) { |
| 6961 | 7265 | config2 = config2 || {}; |
| 6962 | 7266 | var config = {}; |
| 6963 | 7267 | |
| 6964 | - var valueFromConfig2Keys = ['url', 'method', 'data']; | |
| 6965 | - var mergeDeepPropertiesKeys = ['headers', 'auth', 'proxy', 'params']; | |
| 6966 | - var defaultToConfig2Keys = [ | |
| 6967 | - 'baseURL', 'transformRequest', 'transformResponse', 'paramsSerializer', | |
| 6968 | - 'timeout', 'timeoutMessage', 'withCredentials', 'adapter', 'responseType', 'xsrfCookieName', | |
| 6969 | - 'xsrfHeaderName', 'onUploadProgress', 'onDownloadProgress', 'decompress', | |
| 6970 | - 'maxContentLength', 'maxBodyLength', 'maxRedirects', 'transport', 'httpAgent', | |
| 6971 | - 'httpsAgent', 'cancelToken', 'socketPath', 'responseEncoding' | |
| 6972 | - ]; | |
| 6973 | - var directMergeKeys = ['validateStatus']; | |
| 6974 | - | |
| 6975 | 7268 | function getMergedValue(target, source) { |
| 6976 | 7269 | if (utils.isPlainObject(target) && utils.isPlainObject(source)) { |
| 6977 | 7270 | return utils.merge(target, source); |
| ... | ... | @@ -6983,56 +7276,170 @@ var ZLMRTCClient = (function (exports) { |
| 6983 | 7276 | return source; |
| 6984 | 7277 | } |
| 6985 | 7278 | |
| 7279 | + // eslint-disable-next-line consistent-return | |
| 6986 | 7280 | function mergeDeepProperties(prop) { |
| 6987 | 7281 | if (!utils.isUndefined(config2[prop])) { |
| 6988 | - config[prop] = getMergedValue(config1[prop], config2[prop]); | |
| 7282 | + return getMergedValue(config1[prop], config2[prop]); | |
| 6989 | 7283 | } else if (!utils.isUndefined(config1[prop])) { |
| 6990 | - config[prop] = getMergedValue(undefined, config1[prop]); | |
| 7284 | + return getMergedValue(undefined, config1[prop]); | |
| 6991 | 7285 | } |
| 6992 | 7286 | } |
| 6993 | 7287 | |
| 6994 | - utils.forEach(valueFromConfig2Keys, function valueFromConfig2(prop) { | |
| 7288 | + // eslint-disable-next-line consistent-return | |
| 7289 | + function valueFromConfig2(prop) { | |
| 6995 | 7290 | if (!utils.isUndefined(config2[prop])) { |
| 6996 | - config[prop] = getMergedValue(undefined, config2[prop]); | |
| 7291 | + return getMergedValue(undefined, config2[prop]); | |
| 6997 | 7292 | } |
| 6998 | - }); | |
| 6999 | - | |
| 7000 | - utils.forEach(mergeDeepPropertiesKeys, mergeDeepProperties); | |
| 7293 | + } | |
| 7001 | 7294 | |
| 7002 | - utils.forEach(defaultToConfig2Keys, function defaultToConfig2(prop) { | |
| 7295 | + // eslint-disable-next-line consistent-return | |
| 7296 | + function defaultToConfig2(prop) { | |
| 7003 | 7297 | if (!utils.isUndefined(config2[prop])) { |
| 7004 | - config[prop] = getMergedValue(undefined, config2[prop]); | |
| 7298 | + return getMergedValue(undefined, config2[prop]); | |
| 7005 | 7299 | } else if (!utils.isUndefined(config1[prop])) { |
| 7006 | - config[prop] = getMergedValue(undefined, config1[prop]); | |
| 7300 | + return getMergedValue(undefined, config1[prop]); | |
| 7007 | 7301 | } |
| 7008 | - }); | |
| 7302 | + } | |
| 7009 | 7303 | |
| 7010 | - utils.forEach(directMergeKeys, function merge(prop) { | |
| 7304 | + // eslint-disable-next-line consistent-return | |
| 7305 | + function mergeDirectKeys(prop) { | |
| 7011 | 7306 | if (prop in config2) { |
| 7012 | - config[prop] = getMergedValue(config1[prop], config2[prop]); | |
| 7307 | + return getMergedValue(config1[prop], config2[prop]); | |
| 7013 | 7308 | } else if (prop in config1) { |
| 7014 | - config[prop] = getMergedValue(undefined, config1[prop]); | |
| 7015 | - } | |
| 7309 | + return getMergedValue(undefined, config1[prop]); | |
| 7310 | + } | |
| 7311 | + } | |
| 7312 | + | |
| 7313 | + var mergeMap = { | |
| 7314 | + 'url': valueFromConfig2, | |
| 7315 | + 'method': valueFromConfig2, | |
| 7316 | + 'data': valueFromConfig2, | |
| 7317 | + 'baseURL': defaultToConfig2, | |
| 7318 | + 'transformRequest': defaultToConfig2, | |
| 7319 | + 'transformResponse': defaultToConfig2, | |
| 7320 | + 'paramsSerializer': defaultToConfig2, | |
| 7321 | + 'timeout': defaultToConfig2, | |
| 7322 | + 'timeoutMessage': defaultToConfig2, | |
| 7323 | + 'withCredentials': defaultToConfig2, | |
| 7324 | + 'adapter': defaultToConfig2, | |
| 7325 | + 'responseType': defaultToConfig2, | |
| 7326 | + 'xsrfCookieName': defaultToConfig2, | |
| 7327 | + 'xsrfHeaderName': defaultToConfig2, | |
| 7328 | + 'onUploadProgress': defaultToConfig2, | |
| 7329 | + 'onDownloadProgress': defaultToConfig2, | |
| 7330 | + 'decompress': defaultToConfig2, | |
| 7331 | + 'maxContentLength': defaultToConfig2, | |
| 7332 | + 'maxBodyLength': defaultToConfig2, | |
| 7333 | + 'beforeRedirect': defaultToConfig2, | |
| 7334 | + 'transport': defaultToConfig2, | |
| 7335 | + 'httpAgent': defaultToConfig2, | |
| 7336 | + 'httpsAgent': defaultToConfig2, | |
| 7337 | + 'cancelToken': defaultToConfig2, | |
| 7338 | + 'socketPath': defaultToConfig2, | |
| 7339 | + 'responseEncoding': defaultToConfig2, | |
| 7340 | + 'validateStatus': mergeDirectKeys | |
| 7341 | + }; | |
| 7342 | + | |
| 7343 | + utils.forEach(Object.keys(config1).concat(Object.keys(config2)), function computeConfigValue(prop) { | |
| 7344 | + var merge = mergeMap[prop] || mergeDeepProperties; | |
| 7345 | + var configValue = merge(prop); | |
| 7346 | + (utils.isUndefined(configValue) && merge !== mergeDirectKeys) || (config[prop] = configValue); | |
| 7016 | 7347 | }); |
| 7017 | 7348 | |
| 7018 | - var axiosKeys = valueFromConfig2Keys | |
| 7019 | - .concat(mergeDeepPropertiesKeys) | |
| 7020 | - .concat(defaultToConfig2Keys) | |
| 7021 | - .concat(directMergeKeys); | |
| 7349 | + return config; | |
| 7350 | + }; | |
| 7022 | 7351 | |
| 7023 | - var otherKeys = Object | |
| 7024 | - .keys(config1) | |
| 7025 | - .concat(Object.keys(config2)) | |
| 7026 | - .filter(function filterAxiosKeys(key) { | |
| 7027 | - return axiosKeys.indexOf(key) === -1; | |
| 7028 | - }); | |
| 7352 | + var data = { | |
| 7353 | + "version": "0.27.2" | |
| 7354 | + }; | |
| 7029 | 7355 | |
| 7030 | - utils.forEach(otherKeys, mergeDeepProperties); | |
| 7356 | + var VERSION = data.version; | |
| 7031 | 7357 | |
| 7032 | - return config; | |
| 7358 | + | |
| 7359 | + var validators$1 = {}; | |
| 7360 | + | |
| 7361 | + // eslint-disable-next-line func-names | |
| 7362 | + ['object', 'boolean', 'number', 'function', 'string', 'symbol'].forEach(function(type, i) { | |
| 7363 | + validators$1[type] = function validator(thing) { | |
| 7364 | + return typeof thing === type || 'a' + (i < 1 ? 'n ' : ' ') + type; | |
| 7365 | + }; | |
| 7366 | + }); | |
| 7367 | + | |
| 7368 | + var deprecatedWarnings = {}; | |
| 7369 | + | |
| 7370 | + /** | |
| 7371 | + * Transitional option validator | |
| 7372 | + * @param {function|boolean?} validator - set to false if the transitional option has been removed | |
| 7373 | + * @param {string?} version - deprecated version / removed since version | |
| 7374 | + * @param {string?} message - some message with additional info | |
| 7375 | + * @returns {function} | |
| 7376 | + */ | |
| 7377 | + validators$1.transitional = function transitional(validator, version, message) { | |
| 7378 | + function formatMessage(opt, desc) { | |
| 7379 | + return '[Axios v' + VERSION + '] Transitional option \'' + opt + '\'' + desc + (message ? '. ' + message : ''); | |
| 7380 | + } | |
| 7381 | + | |
| 7382 | + // eslint-disable-next-line func-names | |
| 7383 | + return function(value, opt, opts) { | |
| 7384 | + if (validator === false) { | |
| 7385 | + throw new AxiosError_1( | |
| 7386 | + formatMessage(opt, ' has been removed' + (version ? ' in ' + version : '')), | |
| 7387 | + AxiosError_1.ERR_DEPRECATED | |
| 7388 | + ); | |
| 7389 | + } | |
| 7390 | + | |
| 7391 | + if (version && !deprecatedWarnings[opt]) { | |
| 7392 | + deprecatedWarnings[opt] = true; | |
| 7393 | + // eslint-disable-next-line no-console | |
| 7394 | + console.warn( | |
| 7395 | + formatMessage( | |
| 7396 | + opt, | |
| 7397 | + ' has been deprecated since v' + version + ' and will be removed in the near future' | |
| 7398 | + ) | |
| 7399 | + ); | |
| 7400 | + } | |
| 7401 | + | |
| 7402 | + return validator ? validator(value, opt, opts) : true; | |
| 7403 | + }; | |
| 7033 | 7404 | }; |
| 7034 | 7405 | |
| 7035 | 7406 | /** |
| 7407 | + * Assert object's properties type | |
| 7408 | + * @param {object} options | |
| 7409 | + * @param {object} schema | |
| 7410 | + * @param {boolean?} allowUnknown | |
| 7411 | + */ | |
| 7412 | + | |
| 7413 | + function assertOptions(options, schema, allowUnknown) { | |
| 7414 | + if (typeof options !== 'object') { | |
| 7415 | + throw new AxiosError_1('options must be an object', AxiosError_1.ERR_BAD_OPTION_VALUE); | |
| 7416 | + } | |
| 7417 | + var keys = Object.keys(options); | |
| 7418 | + var i = keys.length; | |
| 7419 | + while (i-- > 0) { | |
| 7420 | + var opt = keys[i]; | |
| 7421 | + var validator = schema[opt]; | |
| 7422 | + if (validator) { | |
| 7423 | + var value = options[opt]; | |
| 7424 | + var result = value === undefined || validator(value, opt, options); | |
| 7425 | + if (result !== true) { | |
| 7426 | + throw new AxiosError_1('option ' + opt + ' must be ' + result, AxiosError_1.ERR_BAD_OPTION_VALUE); | |
| 7427 | + } | |
| 7428 | + continue; | |
| 7429 | + } | |
| 7430 | + if (allowUnknown !== true) { | |
| 7431 | + throw new AxiosError_1('Unknown option ' + opt, AxiosError_1.ERR_BAD_OPTION); | |
| 7432 | + } | |
| 7433 | + } | |
| 7434 | + } | |
| 7435 | + | |
| 7436 | + var validator = { | |
| 7437 | + assertOptions: assertOptions, | |
| 7438 | + validators: validators$1 | |
| 7439 | + }; | |
| 7440 | + | |
| 7441 | + var validators = validator.validators; | |
| 7442 | + /** | |
| 7036 | 7443 | * Create a new instance of Axios |
| 7037 | 7444 | * |
| 7038 | 7445 | * @param {Object} instanceConfig The default config for the instance |
| ... | ... | @@ -7050,14 +7457,14 @@ var ZLMRTCClient = (function (exports) { |
| 7050 | 7457 | * |
| 7051 | 7458 | * @param {Object} config The config specific for this request (merged with this.defaults) |
| 7052 | 7459 | */ |
| 7053 | - Axios.prototype.request = function request(config) { | |
| 7460 | + Axios.prototype.request = function request(configOrUrl, config) { | |
| 7054 | 7461 | /*eslint no-param-reassign:0*/ |
| 7055 | 7462 | // Allow for axios('example/url'[, config]) a la fetch API |
| 7056 | - if (typeof config === 'string') { | |
| 7057 | - config = arguments[1] || {}; | |
| 7058 | - config.url = arguments[0]; | |
| 7059 | - } else { | |
| 7463 | + if (typeof configOrUrl === 'string') { | |
| 7060 | 7464 | config = config || {}; |
| 7465 | + config.url = configOrUrl; | |
| 7466 | + } else { | |
| 7467 | + config = configOrUrl || {}; | |
| 7061 | 7468 | } |
| 7062 | 7469 | |
| 7063 | 7470 | config = mergeConfig(this.defaults, config); |
| ... | ... | @@ -7071,20 +7478,71 @@ var ZLMRTCClient = (function (exports) { |
| 7071 | 7478 | config.method = 'get'; |
| 7072 | 7479 | } |
| 7073 | 7480 | |
| 7074 | - // Hook up interceptors middleware | |
| 7075 | - var chain = [dispatchRequest, undefined]; | |
| 7076 | - var promise = Promise.resolve(config); | |
| 7481 | + var transitional = config.transitional; | |
| 7482 | + | |
| 7483 | + if (transitional !== undefined) { | |
| 7484 | + validator.assertOptions(transitional, { | |
| 7485 | + silentJSONParsing: validators.transitional(validators.boolean), | |
| 7486 | + forcedJSONParsing: validators.transitional(validators.boolean), | |
| 7487 | + clarifyTimeoutError: validators.transitional(validators.boolean) | |
| 7488 | + }, false); | |
| 7489 | + } | |
| 7077 | 7490 | |
| 7491 | + // filter out skipped interceptors | |
| 7492 | + var requestInterceptorChain = []; | |
| 7493 | + var synchronousRequestInterceptors = true; | |
| 7078 | 7494 | this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) { |
| 7079 | - chain.unshift(interceptor.fulfilled, interceptor.rejected); | |
| 7495 | + if (typeof interceptor.runWhen === 'function' && interceptor.runWhen(config) === false) { | |
| 7496 | + return; | |
| 7497 | + } | |
| 7498 | + | |
| 7499 | + synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous; | |
| 7500 | + | |
| 7501 | + requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected); | |
| 7080 | 7502 | }); |
| 7081 | 7503 | |
| 7504 | + var responseInterceptorChain = []; | |
| 7082 | 7505 | this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) { |
| 7083 | - chain.push(interceptor.fulfilled, interceptor.rejected); | |
| 7506 | + responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected); | |
| 7084 | 7507 | }); |
| 7085 | 7508 | |
| 7086 | - while (chain.length) { | |
| 7087 | - promise = promise.then(chain.shift(), chain.shift()); | |
| 7509 | + var promise; | |
| 7510 | + | |
| 7511 | + if (!synchronousRequestInterceptors) { | |
| 7512 | + var chain = [dispatchRequest, undefined]; | |
| 7513 | + | |
| 7514 | + Array.prototype.unshift.apply(chain, requestInterceptorChain); | |
| 7515 | + chain = chain.concat(responseInterceptorChain); | |
| 7516 | + | |
| 7517 | + promise = Promise.resolve(config); | |
| 7518 | + while (chain.length) { | |
| 7519 | + promise = promise.then(chain.shift(), chain.shift()); | |
| 7520 | + } | |
| 7521 | + | |
| 7522 | + return promise; | |
| 7523 | + } | |
| 7524 | + | |
| 7525 | + | |
| 7526 | + var newConfig = config; | |
| 7527 | + while (requestInterceptorChain.length) { | |
| 7528 | + var onFulfilled = requestInterceptorChain.shift(); | |
| 7529 | + var onRejected = requestInterceptorChain.shift(); | |
| 7530 | + try { | |
| 7531 | + newConfig = onFulfilled(newConfig); | |
| 7532 | + } catch (error) { | |
| 7533 | + onRejected(error); | |
| 7534 | + break; | |
| 7535 | + } | |
| 7536 | + } | |
| 7537 | + | |
| 7538 | + try { | |
| 7539 | + promise = dispatchRequest(newConfig); | |
| 7540 | + } catch (error) { | |
| 7541 | + return Promise.reject(error); | |
| 7542 | + } | |
| 7543 | + | |
| 7544 | + while (responseInterceptorChain.length) { | |
| 7545 | + promise = promise.then(responseInterceptorChain.shift(), responseInterceptorChain.shift()); | |
| 7088 | 7546 | } |
| 7089 | 7547 | |
| 7090 | 7548 | return promise; |
| ... | ... | @@ -7092,7 +7550,8 @@ var ZLMRTCClient = (function (exports) { |
| 7092 | 7550 | |
| 7093 | 7551 | Axios.prototype.getUri = function getUri(config) { |
| 7094 | 7552 | config = mergeConfig(this.defaults, config); |
| 7095 | - return buildURL(config.url, config.params, config.paramsSerializer).replace(/^\?/, ''); | |
| 7553 | + var fullPath = buildFullPath(config.baseURL, config.url); | |
| 7554 | + return buildURL(fullPath, config.params, config.paramsSerializer); | |
| 7096 | 7555 | }; |
| 7097 | 7556 | |
| 7098 | 7557 | // Provide aliases for supported request methods |
| ... | ... | @@ -7109,34 +7568,26 @@ var ZLMRTCClient = (function (exports) { |
| 7109 | 7568 | |
| 7110 | 7569 | utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { |
| 7111 | 7570 | /*eslint func-names:0*/ |
| 7112 | - Axios.prototype[method] = function(url, data, config) { | |
| 7113 | - return this.request(mergeConfig(config || {}, { | |
| 7114 | - method: method, | |
| 7115 | - url: url, | |
| 7116 | - data: data | |
| 7117 | - })); | |
| 7118 | - }; | |
| 7119 | - }); | |
| 7120 | - | |
| 7121 | - var Axios_1 = Axios; | |
| 7122 | 7571 | |
| 7123 | - /** | |
| 7124 | - * A `Cancel` is an object that is thrown when an operation is canceled. | |
| 7125 | - * | |
| 7126 | - * @class | |
| 7127 | - * @param {string=} message The message. | |
| 7128 | - */ | |
| 7129 | - function Cancel(message) { | |
| 7130 | - this.message = message; | |
| 7131 | - } | |
| 7572 | + function generateHTTPMethod(isForm) { | |
| 7573 | + return function httpMethod(url, data, config) { | |
| 7574 | + return this.request(mergeConfig(config || {}, { | |
| 7575 | + method: method, | |
| 7576 | + headers: isForm ? { | |
| 7577 | + 'Content-Type': 'multipart/form-data' | |
| 7578 | + } : {}, | |
| 7579 | + url: url, | |
| 7580 | + data: data | |
| 7581 | + })); | |
| 7582 | + }; | |
| 7583 | + } | |
| 7132 | 7584 | |
| 7133 | - Cancel.prototype.toString = function toString() { | |
| 7134 | - return 'Cancel' + (this.message ? ': ' + this.message : ''); | |
| 7135 | - }; | |
| 7585 | + Axios.prototype[method] = generateHTTPMethod(); | |
| 7136 | 7586 | |
| 7137 | - Cancel.prototype.__CANCEL__ = true; | |
| 7587 | + Axios.prototype[method + 'Form'] = generateHTTPMethod(true); | |
| 7588 | + }); | |
| 7138 | 7589 | |
| 7139 | - var Cancel_1 = Cancel; | |
| 7590 | + var Axios_1 = Axios; | |
| 7140 | 7591 | |
| 7141 | 7592 | /** |
| 7142 | 7593 | * A `CancelToken` is an object that can be used to request cancellation of an operation. |
| ... | ... | @@ -7150,24 +7601,55 @@ var ZLMRTCClient = (function (exports) { |
| 7150 | 7601 | } |
| 7151 | 7602 | |
| 7152 | 7603 | var resolvePromise; |
| 7604 | + | |
| 7153 | 7605 | this.promise = new Promise(function promiseExecutor(resolve) { |
| 7154 | 7606 | resolvePromise = resolve; |
| 7155 | 7607 | }); |
| 7156 | 7608 | |
| 7157 | 7609 | var token = this; |
| 7610 | + | |
| 7611 | + // eslint-disable-next-line func-names | |
| 7612 | + this.promise.then(function(cancel) { | |
| 7613 | + if (!token._listeners) return; | |
| 7614 | + | |
| 7615 | + var i; | |
| 7616 | + var l = token._listeners.length; | |
| 7617 | + | |
| 7618 | + for (i = 0; i < l; i++) { | |
| 7619 | + token._listeners[i](cancel); | |
| 7620 | + } | |
| 7621 | + token._listeners = null; | |
| 7622 | + }); | |
| 7623 | + | |
| 7624 | + // eslint-disable-next-line func-names | |
| 7625 | + this.promise.then = function(onfulfilled) { | |
| 7626 | + var _resolve; | |
| 7627 | + // eslint-disable-next-line func-names | |
| 7628 | + var promise = new Promise(function(resolve) { | |
| 7629 | + token.subscribe(resolve); | |
| 7630 | + _resolve = resolve; | |
| 7631 | + }).then(onfulfilled); | |
| 7632 | + | |
| 7633 | + promise.cancel = function reject() { | |
| 7634 | + token.unsubscribe(_resolve); | |
| 7635 | + }; | |
| 7636 | + | |
| 7637 | + return promise; | |
| 7638 | + }; | |
| 7639 | + | |
| 7158 | 7640 | executor(function cancel(message) { |
| 7159 | 7641 | if (token.reason) { |
| 7160 | 7642 | // Cancellation has already been requested |
| 7161 | 7643 | return; |
| 7162 | 7644 | } |
| 7163 | 7645 | |
| 7164 | - token.reason = new Cancel_1(message); | |
| 7646 | + token.reason = new CanceledError_1(message); | |
| 7165 | 7647 | resolvePromise(token.reason); |
| 7166 | 7648 | }); |
| 7167 | 7649 | } |
| 7168 | 7650 | |
| 7169 | 7651 | /** |
| 7170 | - * Throws a `Cancel` if cancellation has been requested. | |
| 7652 | + * Throws a `CanceledError` if cancellation has been requested. | |
| 7171 | 7653 | */ |
| 7172 | 7654 | CancelToken.prototype.throwIfRequested = function throwIfRequested() { |
| 7173 | 7655 | if (this.reason) { |
| ... | ... | @@ -7176,6 +7658,37 @@ var ZLMRTCClient = (function (exports) { |
| 7176 | 7658 | }; |
| 7177 | 7659 | |
| 7178 | 7660 | /** |
| 7661 | + * Subscribe to the cancel signal | |
| 7662 | + */ | |
| 7663 | + | |
| 7664 | + CancelToken.prototype.subscribe = function subscribe(listener) { | |
| 7665 | + if (this.reason) { | |
| 7666 | + listener(this.reason); | |
| 7667 | + return; | |
| 7668 | + } | |
| 7669 | + | |
| 7670 | + if (this._listeners) { | |
| 7671 | + this._listeners.push(listener); | |
| 7672 | + } else { | |
| 7673 | + this._listeners = [listener]; | |
| 7674 | + } | |
| 7675 | + }; | |
| 7676 | + | |
| 7677 | + /** | |
| 7678 | + * Unsubscribe from the cancel signal | |
| 7679 | + */ | |
| 7680 | + | |
| 7681 | + CancelToken.prototype.unsubscribe = function unsubscribe(listener) { | |
| 7682 | + if (!this._listeners) { | |
| 7683 | + return; | |
| 7684 | + } | |
| 7685 | + var index = this._listeners.indexOf(listener); | |
| 7686 | + if (index !== -1) { | |
| 7687 | + this._listeners.splice(index, 1); | |
| 7688 | + } | |
| 7689 | + }; | |
| 7690 | + | |
| 7691 | + /** | |
| 7179 | 7692 | * Returns an object that contains a new `CancelToken` and a function that, when called, |
| 7180 | 7693 | * cancels the `CancelToken`. |
| 7181 | 7694 | */ |
| ... | ... | @@ -7225,7 +7738,7 @@ var ZLMRTCClient = (function (exports) { |
| 7225 | 7738 | * @returns {boolean} True if the payload is an error thrown by Axios, otherwise false |
| 7226 | 7739 | */ |
| 7227 | 7740 | var isAxiosError = function isAxiosError(payload) { |
| 7228 | - return (typeof payload === 'object') && (payload.isAxiosError === true); | |
| 7741 | + return utils.isObject(payload) && (payload.isAxiosError === true); | |
| 7229 | 7742 | }; |
| 7230 | 7743 | |
| 7231 | 7744 | /** |
| ... | ... | @@ -7244,6 +7757,11 @@ var ZLMRTCClient = (function (exports) { |
| 7244 | 7757 | // Copy context to instance |
| 7245 | 7758 | utils.extend(instance, context); |
| 7246 | 7759 | |
| 7760 | + // Factory for creating new instances | |
| 7761 | + instance.create = function create(instanceConfig) { | |
| 7762 | + return createInstance(mergeConfig(defaultConfig, instanceConfig)); | |
| 7763 | + }; | |
| 7764 | + | |
| 7247 | 7765 | return instance; |
| 7248 | 7766 | } |
| 7249 | 7767 | |
| ... | ... | @@ -7253,15 +7771,18 @@ var ZLMRTCClient = (function (exports) { |
| 7253 | 7771 | // Expose Axios class to allow class inheritance |
| 7254 | 7772 | axios$1.Axios = Axios_1; |
| 7255 | 7773 | |
| 7256 | - // Factory for creating new instances | |
| 7257 | - axios$1.create = function create(instanceConfig) { | |
| 7258 | - return createInstance(mergeConfig(axios$1.defaults, instanceConfig)); | |
| 7259 | - }; | |
| 7260 | - | |
| 7261 | 7774 | // Expose Cancel & CancelToken |
| 7262 | - axios$1.Cancel = Cancel_1; | |
| 7775 | + axios$1.CanceledError = CanceledError_1; | |
| 7263 | 7776 | axios$1.CancelToken = CancelToken_1; |
| 7264 | 7777 | axios$1.isCancel = isCancel; |
| 7778 | + axios$1.VERSION = data.version; | |
| 7779 | + axios$1.toFormData = toFormData_1; | |
| 7780 | + | |
| 7781 | + // Expose AxiosError class | |
| 7782 | + axios$1.AxiosError = AxiosError_1; | |
| 7783 | + | |
| 7784 | + // alias for CanceledError for backward compatibility | |
| 7785 | + axios$1.Cancel = axios$1.CanceledError; | |
| 7265 | 7786 | |
| 7266 | 7787 | // Expose all/spread |
| 7267 | 7788 | axios$1.all = function all(promises) { |
| ... | ... | @@ -7302,11 +7823,9 @@ var ZLMRTCClient = (function (exports) { |
| 7302 | 7823 | usedatachannel: false |
| 7303 | 7824 | }; |
| 7304 | 7825 | this.options = Object.assign({}, defaults, options); |
| 7305 | - | |
| 7306 | 7826 | if (this.options.debug) { |
| 7307 | 7827 | setLogger(); |
| 7308 | 7828 | } |
| 7309 | - | |
| 7310 | 7829 | this.e = { |
| 7311 | 7830 | onicecandidate: this._onIceCandidate.bind(this), |
| 7312 | 7831 | ontrack: this._onTrack.bind(this), |
| ... | ... | @@ -7319,13 +7838,13 @@ var ZLMRTCClient = (function (exports) { |
| 7319 | 7838 | }; |
| 7320 | 7839 | this._remoteStream = null; |
| 7321 | 7840 | this._localStream = null; |
| 7841 | + this._tracks = []; | |
| 7322 | 7842 | this.pc = new RTCPeerConnection(null); |
| 7323 | 7843 | this.pc.onicecandidate = this.e.onicecandidate; |
| 7324 | 7844 | this.pc.onicecandidateerror = this.e.onicecandidateerror; |
| 7325 | 7845 | this.pc.ontrack = this.e.ontrack; |
| 7326 | 7846 | this.pc.onconnectionstatechange = this.e.onconnectionstatechange; |
| 7327 | 7847 | this.datachannel = null; |
| 7328 | - | |
| 7329 | 7848 | if (this.options.usedatachannel) { |
| 7330 | 7849 | this.datachannel = this.pc.createDataChannel('chat'); |
| 7331 | 7850 | this.datachannel.onclose = this.e.ondatachannelclose; |
| ... | ... | @@ -7333,12 +7852,11 @@ var ZLMRTCClient = (function (exports) { |
| 7333 | 7852 | this.datachannel.onmessage = this.e.ondatachannelmsg; |
| 7334 | 7853 | this.datachannel.onopen = this.e.ondatachannelopen; |
| 7335 | 7854 | } |
| 7336 | - | |
| 7337 | 7855 | if (!this.options.recvOnly && (this.options.audioEnable || this.options.videoEnable)) this.start();else this.receive(); |
| 7338 | 7856 | } |
| 7339 | - | |
| 7340 | 7857 | receive() { |
| 7341 | 7858 | |
| 7859 | + //debug.error(this.TAG,'this not implement'); | |
| 7342 | 7860 | const AudioTransceiverInit = { |
| 7343 | 7861 | direction: 'recvonly', |
| 7344 | 7862 | sendEncodings: [] |
| ... | ... | @@ -7347,8 +7865,12 @@ var ZLMRTCClient = (function (exports) { |
| 7347 | 7865 | direction: 'recvonly', |
| 7348 | 7866 | sendEncodings: [] |
| 7349 | 7867 | }; |
| 7350 | - this.pc.addTransceiver('audio', AudioTransceiverInit); | |
| 7351 | - this.pc.addTransceiver('video', VideoTransceiverInit); | |
| 7868 | + if (this.options.videoEnable) { | |
| 7869 | + this.pc.addTransceiver('video', VideoTransceiverInit); | |
| 7870 | + } | |
| 7871 | + if (this.options.audioEnable) { | |
| 7872 | + this.pc.addTransceiver('audio', AudioTransceiverInit); | |
| 7873 | + } | |
| 7352 | 7874 | this.pc.createOffer().then(desc => { |
| 7353 | 7875 | log(this.TAG, 'offer:', desc.sdp); |
| 7354 | 7876 | this.pc.setLocalDescription(desc).then(() => { |
| ... | ... | @@ -7362,13 +7884,11 @@ var ZLMRTCClient = (function (exports) { |
| 7362 | 7884 | } |
| 7363 | 7885 | }).then(response => { |
| 7364 | 7886 | let ret = response.data; //JSON.parse(response.data); |
| 7365 | - | |
| 7366 | 7887 | if (ret.code != 0) { |
| 7367 | 7888 | // mean failed for offer/anwser exchange |
| 7368 | 7889 | this.dispatch(Events$1.WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED, ret); |
| 7369 | 7890 | return; |
| 7370 | 7891 | } |
| 7371 | - | |
| 7372 | 7892 | let anwser = {}; |
| 7373 | 7893 | anwser.sdp = ret.sdp; |
| 7374 | 7894 | anwser.type = 'answer'; |
| ... | ... | @@ -7384,11 +7904,9 @@ var ZLMRTCClient = (function (exports) { |
| 7384 | 7904 | error(this.TAG, e); |
| 7385 | 7905 | }); |
| 7386 | 7906 | } |
| 7387 | - | |
| 7388 | 7907 | start() { |
| 7389 | 7908 | let videoConstraints = false; |
| 7390 | 7909 | let audioConstraints = false; |
| 7391 | - | |
| 7392 | 7910 | if (this.options.useCamera) { |
| 7393 | 7911 | if (this.options.videoEnable) videoConstraints = new VideoTrackConstraints(VideoSourceInfo.CAMERA); |
| 7394 | 7912 | if (this.options.audioEnable) audioConstraints = new AudioTrackConstraints(AudioSourceInfo.MIC); |
| ... | ... | @@ -7403,11 +7921,9 @@ var ZLMRTCClient = (function (exports) { |
| 7403 | 7921 | } |
| 7404 | 7922 | } |
| 7405 | 7923 | } |
| 7406 | - | |
| 7407 | 7924 | if (this.options.resolution.w != 0 && this.options.resolution.h != 0 && typeof videoConstraints == 'object') { |
| 7408 | 7925 | videoConstraints.resolution = new Resolution(this.options.resolution.w, this.options.resolution.h); |
| 7409 | 7926 | } |
| 7410 | - | |
| 7411 | 7927 | MediaStreamFactory.createMediaStream(new StreamConstraints(audioConstraints, videoConstraints)).then(stream => { |
| 7412 | 7928 | this._localStream = stream; |
| 7413 | 7929 | this.dispatch(Events$1.WEBRTC_ON_LOCAL_STREAM, stream); |
| ... | ... | @@ -7419,7 +7935,6 @@ var ZLMRTCClient = (function (exports) { |
| 7419 | 7935 | direction: 'sendrecv', |
| 7420 | 7936 | sendEncodings: [] |
| 7421 | 7937 | }; |
| 7422 | - | |
| 7423 | 7938 | if (this.options.simulcast && stream.getVideoTracks().length > 0) { |
| 7424 | 7939 | VideoTransceiverInit.sendEncodings = [{ |
| 7425 | 7940 | rid: 'h', |
| ... | ... | @@ -7437,7 +7952,6 @@ var ZLMRTCClient = (function (exports) { |
| 7437 | 7952 | scaleResolutionDownBy: 4 |
| 7438 | 7953 | }]; |
| 7439 | 7954 | } |
| 7440 | - | |
| 7441 | 7955 | if (this.options.audioEnable) { |
| 7442 | 7956 | if (stream.getAudioTracks().length > 0) { |
| 7443 | 7957 | this.pc.addTransceiver(stream.getAudioTracks()[0], AudioTransceiverInit); |
| ... | ... | @@ -7446,7 +7960,6 @@ var ZLMRTCClient = (function (exports) { |
| 7446 | 7960 | this.pc.addTransceiver('audio', AudioTransceiverInit); |
| 7447 | 7961 | } |
| 7448 | 7962 | } |
| 7449 | - | |
| 7450 | 7963 | if (this.options.videoEnable) { |
| 7451 | 7964 | if (stream.getVideoTracks().length > 0) { |
| 7452 | 7965 | this.pc.addTransceiver(stream.getVideoTracks()[0], VideoTransceiverInit); |
| ... | ... | @@ -7455,14 +7968,13 @@ var ZLMRTCClient = (function (exports) { |
| 7455 | 7968 | this.pc.addTransceiver('video', VideoTransceiverInit); |
| 7456 | 7969 | } |
| 7457 | 7970 | } |
| 7971 | + | |
| 7458 | 7972 | /* |
| 7459 | 7973 | stream.getTracks().forEach((track,idx)=>{ |
| 7460 | 7974 | debug.log(this.TAG,track); |
| 7461 | 7975 | this.pc.addTrack(track); |
| 7462 | 7976 | }); |
| 7463 | 7977 | */ |
| 7464 | - | |
| 7465 | - | |
| 7466 | 7978 | this.pc.createOffer().then(desc => { |
| 7467 | 7979 | log(this.TAG, 'offer:', desc.sdp); |
| 7468 | 7980 | this.pc.setLocalDescription(desc).then(() => { |
| ... | ... | @@ -7476,13 +7988,11 @@ var ZLMRTCClient = (function (exports) { |
| 7476 | 7988 | } |
| 7477 | 7989 | }).then(response => { |
| 7478 | 7990 | let ret = response.data; //JSON.parse(response.data); |
| 7479 | - | |
| 7480 | 7991 | if (ret.code != 0) { |
| 7481 | 7992 | // mean failed for offer/anwser exchange |
| 7482 | 7993 | this.dispatch(Events$1.WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED, ret); |
| 7483 | 7994 | return; |
| 7484 | 7995 | } |
| 7485 | - | |
| 7486 | 7996 | let anwser = {}; |
| 7487 | 7997 | anwser.sdp = ret.sdp; |
| 7488 | 7998 | anwser.type = 'answer'; |
| ... | ... | @@ -7498,9 +8008,11 @@ var ZLMRTCClient = (function (exports) { |
| 7498 | 8008 | error(this.TAG, e); |
| 7499 | 8009 | }); |
| 7500 | 8010 | }).catch(e => { |
| 7501 | - this.dispatch(Events$1.CAPTURE_STREAM_FAILED); //debug.error(this.TAG,e); | |
| 7502 | - }); //const offerOptions = {}; | |
| 8011 | + this.dispatch(Events$1.CAPTURE_STREAM_FAILED); | |
| 8012 | + //debug.error(this.TAG,e); | |
| 8013 | + }); | |
| 7503 | 8014 | |
| 8015 | + //const offerOptions = {}; | |
| 7504 | 8016 | /* |
| 7505 | 8017 | if (typeof this.pc.addTransceiver === 'function') { |
| 7506 | 8018 | // |direction| seems not working on Safari. |
| ... | ... | @@ -7515,48 +8027,48 @@ var ZLMRTCClient = (function (exports) { |
| 7515 | 8027 | |
| 7516 | 8028 | _onIceCandidate(event) { |
| 7517 | 8029 | if (event.candidate) { |
| 7518 | - log('Remote ICE candidate: \n ' + event.candidate.candidate); // Send the candidate to the remote peer | |
| 8030 | + log(this.TAG, 'Remote ICE candidate: \n ' + event.candidate.candidate); | |
| 8031 | + // Send the candidate to the remote peer | |
| 7519 | 8032 | } |
| 7520 | 8033 | } |
| 7521 | - | |
| 7522 | 8034 | _onTrack(event) { |
| 8035 | + this._tracks.push(event.track); | |
| 7523 | 8036 | if (this.options.element && event.streams && event.streams.length > 0) { |
| 7524 | 8037 | this.options.element.srcObject = event.streams[0]; |
| 7525 | 8038 | this._remoteStream = event.streams[0]; |
| 7526 | 8039 | this.dispatch(Events$1.WEBRTC_ON_REMOTE_STREAMS, event); |
| 7527 | 8040 | } else { |
| 7528 | - error('element pararm is failed'); | |
| 8041 | + if (this.pc.getReceivers().length == this._tracks.length) { | |
| 8042 | + log(this.TAG, 'play remote stream '); | |
| 8043 | + this._remoteStream = new MediaStream(this._tracks); | |
| 8044 | + this.options.element.srcObject = this._remoteStream; | |
| 8045 | + } else { | |
| 8046 | + error(this.TAG, 'wait stream track finish'); | |
| 8047 | + } | |
| 7529 | 8048 | } |
| 7530 | 8049 | } |
| 7531 | - | |
| 7532 | 8050 | _onIceCandidateError(event) { |
| 7533 | 8051 | this.dispatch(Events$1.WEBRTC_ICE_CANDIDATE_ERROR, event); |
| 7534 | 8052 | } |
| 7535 | - | |
| 7536 | 8053 | _onconnectionstatechange(event) { |
| 7537 | 8054 | this.dispatch(Events$1.WEBRTC_ON_CONNECTION_STATE_CHANGE, this.pc.connectionState); |
| 7538 | 8055 | } |
| 7539 | - | |
| 7540 | 8056 | _onDataChannelOpen(event) { |
| 7541 | 8057 | log(this.TAG, 'ondatachannel open:', event); |
| 7542 | 8058 | this.dispatch(Events$1.WEBRTC_ON_DATA_CHANNEL_OPEN, event); |
| 7543 | 8059 | } |
| 7544 | - | |
| 7545 | 8060 | _onDataChannelMsg(event) { |
| 7546 | 8061 | log(this.TAG, 'ondatachannel msg:', event); |
| 7547 | 8062 | this.dispatch(Events$1.WEBRTC_ON_DATA_CHANNEL_MSG, event); |
| 7548 | 8063 | } |
| 7549 | - | |
| 7550 | 8064 | _onDataChannelErr(event) { |
| 7551 | 8065 | log(this.TAG, 'ondatachannel err:', event); |
| 7552 | 8066 | this.dispatch(Events$1.WEBRTC_ON_DATA_CHANNEL_ERR, event); |
| 7553 | 8067 | } |
| 7554 | - | |
| 7555 | 8068 | _onDataChannelClose(event) { |
| 7556 | 8069 | log(this.TAG, 'ondatachannel close:', event); |
| 7557 | 8070 | this.dispatch(Events$1.WEBRTC_ON_DATA_CHANNEL_CLOSE, event); |
| 7558 | 8071 | } |
| 7559 | - | |
| 7560 | 8072 | sendMsg(data) { |
| 7561 | 8073 | if (this.datachannel != null) { |
| 7562 | 8074 | this.datachannel.send(data); |
| ... | ... | @@ -7564,47 +8076,42 @@ var ZLMRTCClient = (function (exports) { |
| 7564 | 8076 | error(this.TAG, 'data channel is null'); |
| 7565 | 8077 | } |
| 7566 | 8078 | } |
| 7567 | - | |
| 7568 | 8079 | closeDataChannel() { |
| 7569 | 8080 | if (this.datachannel) { |
| 7570 | 8081 | this.datachannel.close(); |
| 7571 | 8082 | this.datachannel = null; |
| 7572 | 8083 | } |
| 7573 | 8084 | } |
| 7574 | - | |
| 7575 | 8085 | close() { |
| 7576 | 8086 | this.closeDataChannel(); |
| 7577 | - | |
| 7578 | 8087 | if (this.pc) { |
| 7579 | 8088 | this.pc.close(); |
| 7580 | 8089 | this.pc = null; |
| 7581 | 8090 | } |
| 7582 | - | |
| 7583 | 8091 | if (this.options) { |
| 7584 | 8092 | this.options = null; |
| 7585 | 8093 | } |
| 7586 | - | |
| 7587 | 8094 | if (this._localStream) { |
| 7588 | 8095 | this._localStream.getTracks().forEach((track, idx) => { |
| 7589 | 8096 | track.stop(); |
| 7590 | 8097 | }); |
| 7591 | 8098 | } |
| 7592 | - | |
| 7593 | 8099 | if (this._remoteStream) { |
| 7594 | 8100 | this._remoteStream.getTracks().forEach((track, idx) => { |
| 7595 | 8101 | track.stop(); |
| 7596 | 8102 | }); |
| 7597 | 8103 | } |
| 8104 | + this._tracks.forEach((track, idx) => { | |
| 8105 | + track.stop(); | |
| 8106 | + }); | |
| 8107 | + this._tracks = []; | |
| 7598 | 8108 | } |
| 7599 | - | |
| 7600 | 8109 | get remoteStream() { |
| 7601 | 8110 | return this._remoteStream; |
| 7602 | 8111 | } |
| 7603 | - | |
| 7604 | 8112 | get localStream() { |
| 7605 | 8113 | return this._localStream; |
| 7606 | 8114 | } |
| 7607 | - | |
| 7608 | 8115 | } |
| 7609 | 8116 | |
| 7610 | 8117 | const quickScan = [{ |
| ... | ... | @@ -7658,20 +8165,17 @@ var ZLMRTCClient = (function (exports) { |
| 7658 | 8165 | let resolutions = []; |
| 7659 | 8166 | let ok = 0; |
| 7660 | 8167 | let err = 0; |
| 7661 | - | |
| 7662 | 8168 | for (let i = 0; i < quickScan.length; ++i) { |
| 7663 | 8169 | let videoConstraints = new VideoTrackConstraints(VideoSourceInfo.CAMERA); |
| 7664 | 8170 | videoConstraints.resolution = new Resolution(quickScan[i].width, quickScan[i].height); |
| 7665 | 8171 | MediaStreamFactory.createMediaStream(new StreamConstraints(false, videoConstraints)).then(stream => { |
| 7666 | 8172 | resolutions.push(quickScan[i]); |
| 7667 | 8173 | ok++; |
| 7668 | - | |
| 7669 | 8174 | if (ok + err == quickScan.length) { |
| 7670 | 8175 | resolve(resolutions); |
| 7671 | 8176 | } |
| 7672 | 8177 | }).catch(e => { |
| 7673 | 8178 | err++; |
| 7674 | - | |
| 7675 | 8179 | if (ok + err == quickScan.length) { |
| 7676 | 8180 | resolve(resolutions); |
| 7677 | 8181 | } |
| ... | ... | @@ -7695,7 +8199,7 @@ var ZLMRTCClient = (function (exports) { |
| 7695 | 8199 | } |
| 7696 | 8200 | |
| 7697 | 8201 | console.log('build date:', BUILD_DATE); |
| 7698 | - console.log('version:', VERSION); | |
| 8202 | + console.log('version:', VERSION$1); | |
| 7699 | 8203 | const Events = Events$1; |
| 7700 | 8204 | const Media = media; |
| 7701 | 8205 | const Endpoint = RTCEndpoint; |
| ... | ... | @@ -7714,5 +8218,5 @@ var ZLMRTCClient = (function (exports) { |
| 7714 | 8218 | |
| 7715 | 8219 | return exports; |
| 7716 | 8220 | |
| 7717 | -}({})); | |
| 8221 | +})({}); | |
| 7718 | 8222 | //# sourceMappingURL=ZLMRTCClient.js.map | ... | ... |
web_src/static/js/ZLMRTCClient.js.map
| 1 | -{"version":3,"file":"ZLMRTCClient.js","sources":["../src/base/event.js","../src/ulity/version.js","../src/base/utils.js","../src/base/mediaformat.js","../node_modules/webrtc-adapter/src/js/utils.js","../node_modules/webrtc-adapter/src/js/chrome/getusermedia.js","../node_modules/webrtc-adapter/src/js/chrome/getdisplaymedia.js","../node_modules/webrtc-adapter/src/js/chrome/chrome_shim.js","../node_modules/webrtc-adapter/src/js/edge/filtericeservers.js","../node_modules/sdp/sdp.js","../node_modules/rtcpeerconnection-shim/rtcpeerconnection.js","../node_modules/webrtc-adapter/src/js/edge/getusermedia.js","../node_modules/webrtc-adapter/src/js/edge/getdisplaymedia.js","../node_modules/webrtc-adapter/src/js/edge/edge_shim.js","../node_modules/webrtc-adapter/src/js/firefox/getusermedia.js","../node_modules/webrtc-adapter/src/js/firefox/getdisplaymedia.js","../node_modules/webrtc-adapter/src/js/firefox/firefox_shim.js","../node_modules/webrtc-adapter/src/js/safari/safari_shim.js","../node_modules/webrtc-adapter/src/js/common_shim.js","../node_modules/webrtc-adapter/src/js/adapter_factory.js","../node_modules/webrtc-adapter/src/js/adapter_core.js","../src/base/mediastream-factory.js","../src/base/export.js","../src/ulity/debug.js","../src/ulity/event.js","../node_modules/axios/lib/helpers/bind.js","../node_modules/axios/lib/utils.js","../node_modules/axios/lib/helpers/buildURL.js","../node_modules/axios/lib/core/InterceptorManager.js","../node_modules/axios/lib/core/transformData.js","../node_modules/axios/lib/cancel/isCancel.js","../node_modules/axios/lib/helpers/normalizeHeaderName.js","../node_modules/axios/lib/core/enhanceError.js","../node_modules/axios/lib/core/createError.js","../node_modules/axios/lib/core/settle.js","../node_modules/axios/lib/helpers/cookies.js","../node_modules/axios/lib/helpers/isAbsoluteURL.js","../node_modules/axios/lib/helpers/combineURLs.js","../node_modules/axios/lib/core/buildFullPath.js","../node_modules/axios/lib/helpers/parseHeaders.js","../node_modules/axios/lib/helpers/isURLSameOrigin.js","../node_modules/axios/lib/adapters/xhr.js","../node_modules/axios/lib/defaults.js","../node_modules/axios/lib/core/dispatchRequest.js","../node_modules/axios/lib/core/mergeConfig.js","../node_modules/axios/lib/core/Axios.js","../node_modules/axios/lib/cancel/Cancel.js","../node_modules/axios/lib/cancel/CancelToken.js","../node_modules/axios/lib/helpers/spread.js","../node_modules/axios/lib/helpers/isAxiosError.js","../node_modules/axios/lib/axios.js","../node_modules/axios/index.js","../src/endpoint/endpoint.js","../src/base/resolutionfind.js","../src/export.js"],"sourcesContent":["const Events = {\n\tWEBRTC_NOT_SUPPORT : 'WEBRTC_NOT_SUPPORT',\n\tWEBRTC_ICE_CANDIDATE_ERROR : 'WEBRTC_ICE_CANDIDATE_ERROR',\n\tWEBRTC_OFFER_ANWSER_EXCHANGE_FAILED:'WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED',\n\tWEBRTC_ON_REMOTE_STREAMS:'WEBRTC_ON_REMOTE_STREAMS',\n\tWEBRTC_ON_LOCAL_STREAM:'WEBRTC_ON_LOCAL_STREAM',\n\tWEBRTC_ON_CONNECTION_STATE_CHANGE:'WEBRTC_ON_CONNECTION_STATE_CHANGE',\n\tWEBRTC_ON_DATA_CHANNEL_OPEN:'WEBRTC_ON_DATA_CHANNEL_OPEN',\n\tWEBRTC_ON_DATA_CHANNEL_CLOSE:'WEBRTC_ON_DATA_CHANNEL_CLOSE',\n\tWEBRTC_ON_DATA_CHANNEL_ERR:'WEBRTC_ON_DATA_CHANNEL_ERR',\n\tWEBRTC_ON_DATA_CHANNEL_MSG:'WEBRTC_ON_DATA_CHANNEL_MSG',\n\tCAPTURE_STREAM_FAILED:'CAPTURE_STREAM_FAILED',\n};\n\nexport default Events;","export const VERSION = '__VERSION__';\nexport const BUILD_DATE = '__BUILD_DATE__';","// Copyright (C) <2018> Intel Corporation\n//\n// SPDX-License-Identifier: Apache-2.0\n\n\n// eslint-disable-next-line require-jsdoc\nexport function isFirefox() {\n return window.navigator.userAgent.match('Firefox') !== null;\n}\n// eslint-disable-next-line require-jsdoc\nexport function isChrome() {\n return window.navigator.userAgent.match('Chrome') !== null;\n}\n// eslint-disable-next-line require-jsdoc\nexport function isSafari() {\n return /^((?!chrome|android).)*safari/i.test(window.navigator.userAgent);\n}\n// eslint-disable-next-line require-jsdoc\nexport function isEdge() {\n return window.navigator.userAgent.match(/Edge\\/(\\d+).(\\d+)$/) !== null;\n}\n// eslint-disable-next-line require-jsdoc\nexport function createUuid() {\n return 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n const r = Math.random() * 16 | 0;\n const v = c === 'x' ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n}","// Copyright (C) <2018> Intel Corporation\n//\n// SPDX-License-Identifier: Apache-2.0\n\n'use strict';\n/**\n * @class AudioSourceInfo\n * @classDesc Source info about an audio track. Values: 'mic', 'screen-cast', 'file', 'mixed'.\n * @memberOf Owt.Base\n * @readonly\n * @enum {string}\n */\nexport const AudioSourceInfo = {\n MIC: 'mic',\n SCREENCAST: 'screen-cast',\n FILE: 'file',\n MIXED: 'mixed',\n};\n\n/**\n * @class VideoSourceInfo\n * @classDesc Source info about a video track. Values: 'camera', 'screen-cast', 'file', 'mixed'.\n * @memberOf Owt.Base\n * @readonly\n * @enum {string}\n */\nexport const VideoSourceInfo = {\n CAMERA: 'camera',\n SCREENCAST: 'screen-cast',\n FILE: 'file',\n MIXED: 'mixed',\n};\n\n/**\n * @class TrackKind\n * @classDesc Kind of a track. Values: 'audio' for audio track, 'video' for video track, 'av' for both audio and video tracks.\n * @memberOf Owt.Base\n * @readonly\n * @enum {string}\n */\nexport const TrackKind = {\n /**\n * Audio tracks.\n * @type string\n */\n AUDIO: 'audio',\n /**\n * Video tracks.\n * @type string\n */\n VIDEO: 'video',\n /**\n * Both audio and video tracks.\n * @type string\n */\n AUDIO_AND_VIDEO: 'av',\n};\n/**\n * @class Resolution\n * @memberOf Owt.Base\n * @classDesc The Resolution defines the size of a rectangle.\n * @constructor\n * @param {number} width\n * @param {number} height\n */\nexport class Resolution {\n // eslint-disable-next-line require-jsdoc\n constructor(width, height) {\n /**\n * @member {number} width\n * @instance\n * @memberof Owt.Base.Resolution\n */\n this.width = width;\n /**\n * @member {number} height\n * @instance\n * @memberof Owt.Base.Resolution\n */\n this.height = height;\n }\n}\n","/*\n * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n /* eslint-env node */\n'use strict';\n\nlet logDisabled_ = true;\nlet deprecationWarnings_ = true;\n\n/**\n * Extract browser version out of the provided user agent string.\n *\n * @param {!string} uastring userAgent string.\n * @param {!string} expr Regular expression used as match criteria.\n * @param {!number} pos position in the version string to be returned.\n * @return {!number} browser version.\n */\nexport function extractVersion(uastring, expr, pos) {\n const match = uastring.match(expr);\n return match && match.length >= pos && parseInt(match[pos], 10);\n}\n\n// Wraps the peerconnection event eventNameToWrap in a function\n// which returns the modified event object (or false to prevent\n// the event).\nexport function wrapPeerConnectionEvent(window, eventNameToWrap, wrapper) {\n if (!window.RTCPeerConnection) {\n return;\n }\n const proto = window.RTCPeerConnection.prototype;\n const nativeAddEventListener = proto.addEventListener;\n proto.addEventListener = function(nativeEventName, cb) {\n if (nativeEventName !== eventNameToWrap) {\n return nativeAddEventListener.apply(this, arguments);\n }\n const wrappedCallback = (e) => {\n const modifiedEvent = wrapper(e);\n if (modifiedEvent) {\n if (cb.handleEvent) {\n cb.handleEvent(modifiedEvent);\n } else {\n cb(modifiedEvent);\n }\n }\n };\n this._eventMap = this._eventMap || {};\n if (!this._eventMap[eventNameToWrap]) {\n this._eventMap[eventNameToWrap] = new Map();\n }\n this._eventMap[eventNameToWrap].set(cb, wrappedCallback);\n return nativeAddEventListener.apply(this, [nativeEventName,\n wrappedCallback]);\n };\n\n const nativeRemoveEventListener = proto.removeEventListener;\n proto.removeEventListener = function(nativeEventName, cb) {\n if (nativeEventName !== eventNameToWrap || !this._eventMap\n || !this._eventMap[eventNameToWrap]) {\n return nativeRemoveEventListener.apply(this, arguments);\n }\n if (!this._eventMap[eventNameToWrap].has(cb)) {\n return nativeRemoveEventListener.apply(this, arguments);\n }\n const unwrappedCb = this._eventMap[eventNameToWrap].get(cb);\n this._eventMap[eventNameToWrap].delete(cb);\n if (this._eventMap[eventNameToWrap].size === 0) {\n delete this._eventMap[eventNameToWrap];\n }\n if (Object.keys(this._eventMap).length === 0) {\n delete this._eventMap;\n }\n return nativeRemoveEventListener.apply(this, [nativeEventName,\n unwrappedCb]);\n };\n\n Object.defineProperty(proto, 'on' + eventNameToWrap, {\n get() {\n return this['_on' + eventNameToWrap];\n },\n set(cb) {\n if (this['_on' + eventNameToWrap]) {\n this.removeEventListener(eventNameToWrap,\n this['_on' + eventNameToWrap]);\n delete this['_on' + eventNameToWrap];\n }\n if (cb) {\n this.addEventListener(eventNameToWrap,\n this['_on' + eventNameToWrap] = cb);\n }\n },\n enumerable: true,\n configurable: true\n });\n}\n\nexport function disableLog(bool) {\n if (typeof bool !== 'boolean') {\n return new Error('Argument type: ' + typeof bool +\n '. Please use a boolean.');\n }\n logDisabled_ = bool;\n return (bool) ? 'adapter.js logging disabled' :\n 'adapter.js logging enabled';\n}\n\n/**\n * Disable or enable deprecation warnings\n * @param {!boolean} bool set to true to disable warnings.\n */\nexport function disableWarnings(bool) {\n if (typeof bool !== 'boolean') {\n return new Error('Argument type: ' + typeof bool +\n '. Please use a boolean.');\n }\n deprecationWarnings_ = !bool;\n return 'adapter.js deprecation warnings ' + (bool ? 'disabled' : 'enabled');\n}\n\nexport function log() {\n if (typeof window === 'object') {\n if (logDisabled_) {\n return;\n }\n if (typeof console !== 'undefined' && typeof console.log === 'function') {\n console.log.apply(console, arguments);\n }\n }\n}\n\n/**\n * Shows a deprecation warning suggesting the modern and spec-compatible API.\n */\nexport function deprecated(oldMethod, newMethod) {\n if (!deprecationWarnings_) {\n return;\n }\n console.warn(oldMethod + ' is deprecated, please use ' + newMethod +\n ' instead.');\n}\n\n/**\n * Browser detector.\n *\n * @return {object} result containing browser and version\n * properties.\n */\nexport function detectBrowser(window) {\n // Returned result object.\n const result = {browser: null, version: null};\n\n // Fail early if it's not a browser\n if (typeof window === 'undefined' || !window.navigator) {\n result.browser = 'Not a browser.';\n return result;\n }\n\n const {navigator} = window;\n\n if (navigator.mozGetUserMedia) { // Firefox.\n result.browser = 'firefox';\n result.version = extractVersion(navigator.userAgent,\n /Firefox\\/(\\d+)\\./, 1);\n } else if (navigator.webkitGetUserMedia ||\n (window.isSecureContext === false && window.webkitRTCPeerConnection &&\n !window.RTCIceGatherer)) {\n // Chrome, Chromium, Webview, Opera.\n // Version matches Chrome/WebRTC version.\n // Chrome 74 removed webkitGetUserMedia on http as well so we need the\n // more complicated fallback to webkitRTCPeerConnection.\n result.browser = 'chrome';\n result.version = extractVersion(navigator.userAgent,\n /Chrom(e|ium)\\/(\\d+)\\./, 2);\n } else if (navigator.mediaDevices &&\n navigator.userAgent.match(/Edge\\/(\\d+).(\\d+)$/)) { // Edge.\n result.browser = 'edge';\n result.version = extractVersion(navigator.userAgent,\n /Edge\\/(\\d+).(\\d+)$/, 2);\n } else if (window.RTCPeerConnection &&\n navigator.userAgent.match(/AppleWebKit\\/(\\d+)\\./)) { // Safari.\n result.browser = 'safari';\n result.version = extractVersion(navigator.userAgent,\n /AppleWebKit\\/(\\d+)\\./, 1);\n result.supportsUnifiedPlan = window.RTCRtpTransceiver &&\n 'currentDirection' in window.RTCRtpTransceiver.prototype;\n } else { // Default fallthrough: not supported.\n result.browser = 'Not a supported browser.';\n return result;\n }\n\n return result;\n}\n\n/**\n * Checks if something is an object.\n *\n * @param {*} val The something you want to check.\n * @return true if val is an object, false otherwise.\n */\nfunction isObject(val) {\n return Object.prototype.toString.call(val) === '[object Object]';\n}\n\n/**\n * Remove all empty objects and undefined values\n * from a nested object -- an enhanced and vanilla version\n * of Lodash's `compact`.\n */\nexport function compactObject(data) {\n if (!isObject(data)) {\n return data;\n }\n\n return Object.keys(data).reduce(function(accumulator, key) {\n const isObj = isObject(data[key]);\n const value = isObj ? compactObject(data[key]) : data[key];\n const isEmptyObject = isObj && !Object.keys(value).length;\n if (value === undefined || isEmptyObject) {\n return accumulator;\n }\n return Object.assign(accumulator, {[key]: value});\n }, {});\n}\n\n/* iterates the stats graph recursively. */\nexport function walkStats(stats, base, resultSet) {\n if (!base || resultSet.has(base.id)) {\n return;\n }\n resultSet.set(base.id, base);\n Object.keys(base).forEach(name => {\n if (name.endsWith('Id')) {\n walkStats(stats, stats.get(base[name]), resultSet);\n } else if (name.endsWith('Ids')) {\n base[name].forEach(id => {\n walkStats(stats, stats.get(id), resultSet);\n });\n }\n });\n}\n\n/* filter getStats for a sender/receiver track. */\nexport function filterStats(result, track, outbound) {\n const streamStatsType = outbound ? 'outbound-rtp' : 'inbound-rtp';\n const filteredResult = new Map();\n if (track === null) {\n return filteredResult;\n }\n const trackStats = [];\n result.forEach(value => {\n if (value.type === 'track' &&\n value.trackIdentifier === track.id) {\n trackStats.push(value);\n }\n });\n trackStats.forEach(trackStat => {\n result.forEach(stats => {\n if (stats.type === streamStatsType && stats.trackId === trackStat.id) {\n walkStats(result, stats, filteredResult);\n }\n });\n });\n return filteredResult;\n}\n\n","/*\n * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n/* eslint-env node */\n'use strict';\nimport * as utils from '../utils.js';\nconst logging = utils.log;\n\nexport function shimGetUserMedia(window, browserDetails) {\n const navigator = window && window.navigator;\n\n if (!navigator.mediaDevices) {\n return;\n }\n\n const constraintsToChrome_ = function(c) {\n if (typeof c !== 'object' || c.mandatory || c.optional) {\n return c;\n }\n const cc = {};\n Object.keys(c).forEach(key => {\n if (key === 'require' || key === 'advanced' || key === 'mediaSource') {\n return;\n }\n const r = (typeof c[key] === 'object') ? c[key] : {ideal: c[key]};\n if (r.exact !== undefined && typeof r.exact === 'number') {\n r.min = r.max = r.exact;\n }\n const oldname_ = function(prefix, name) {\n if (prefix) {\n return prefix + name.charAt(0).toUpperCase() + name.slice(1);\n }\n return (name === 'deviceId') ? 'sourceId' : name;\n };\n if (r.ideal !== undefined) {\n cc.optional = cc.optional || [];\n let oc = {};\n if (typeof r.ideal === 'number') {\n oc[oldname_('min', key)] = r.ideal;\n cc.optional.push(oc);\n oc = {};\n oc[oldname_('max', key)] = r.ideal;\n cc.optional.push(oc);\n } else {\n oc[oldname_('', key)] = r.ideal;\n cc.optional.push(oc);\n }\n }\n if (r.exact !== undefined && typeof r.exact !== 'number') {\n cc.mandatory = cc.mandatory || {};\n cc.mandatory[oldname_('', key)] = r.exact;\n } else {\n ['min', 'max'].forEach(mix => {\n if (r[mix] !== undefined) {\n cc.mandatory = cc.mandatory || {};\n cc.mandatory[oldname_(mix, key)] = r[mix];\n }\n });\n }\n });\n if (c.advanced) {\n cc.optional = (cc.optional || []).concat(c.advanced);\n }\n return cc;\n };\n\n const shimConstraints_ = function(constraints, func) {\n if (browserDetails.version >= 61) {\n return func(constraints);\n }\n constraints = JSON.parse(JSON.stringify(constraints));\n if (constraints && typeof constraints.audio === 'object') {\n const remap = function(obj, a, b) {\n if (a in obj && !(b in obj)) {\n obj[b] = obj[a];\n delete obj[a];\n }\n };\n constraints = JSON.parse(JSON.stringify(constraints));\n remap(constraints.audio, 'autoGainControl', 'googAutoGainControl');\n remap(constraints.audio, 'noiseSuppression', 'googNoiseSuppression');\n constraints.audio = constraintsToChrome_(constraints.audio);\n }\n if (constraints && typeof constraints.video === 'object') {\n // Shim facingMode for mobile & surface pro.\n let face = constraints.video.facingMode;\n face = face && ((typeof face === 'object') ? face : {ideal: face});\n const getSupportedFacingModeLies = browserDetails.version < 66;\n\n if ((face && (face.exact === 'user' || face.exact === 'environment' ||\n face.ideal === 'user' || face.ideal === 'environment')) &&\n !(navigator.mediaDevices.getSupportedConstraints &&\n navigator.mediaDevices.getSupportedConstraints().facingMode &&\n !getSupportedFacingModeLies)) {\n delete constraints.video.facingMode;\n let matches;\n if (face.exact === 'environment' || face.ideal === 'environment') {\n matches = ['back', 'rear'];\n } else if (face.exact === 'user' || face.ideal === 'user') {\n matches = ['front'];\n }\n if (matches) {\n // Look for matches in label, or use last cam for back (typical).\n return navigator.mediaDevices.enumerateDevices()\n .then(devices => {\n devices = devices.filter(d => d.kind === 'videoinput');\n let dev = devices.find(d => matches.some(match =>\n d.label.toLowerCase().includes(match)));\n if (!dev && devices.length && matches.includes('back')) {\n dev = devices[devices.length - 1]; // more likely the back cam\n }\n if (dev) {\n constraints.video.deviceId = face.exact ? {exact: dev.deviceId} :\n {ideal: dev.deviceId};\n }\n constraints.video = constraintsToChrome_(constraints.video);\n logging('chrome: ' + JSON.stringify(constraints));\n return func(constraints);\n });\n }\n }\n constraints.video = constraintsToChrome_(constraints.video);\n }\n logging('chrome: ' + JSON.stringify(constraints));\n return func(constraints);\n };\n\n const shimError_ = function(e) {\n if (browserDetails.version >= 64) {\n return e;\n }\n return {\n name: {\n PermissionDeniedError: 'NotAllowedError',\n PermissionDismissedError: 'NotAllowedError',\n InvalidStateError: 'NotAllowedError',\n DevicesNotFoundError: 'NotFoundError',\n ConstraintNotSatisfiedError: 'OverconstrainedError',\n TrackStartError: 'NotReadableError',\n MediaDeviceFailedDueToShutdown: 'NotAllowedError',\n MediaDeviceKillSwitchOn: 'NotAllowedError',\n TabCaptureError: 'AbortError',\n ScreenCaptureError: 'AbortError',\n DeviceCaptureError: 'AbortError'\n }[e.name] || e.name,\n message: e.message,\n constraint: e.constraint || e.constraintName,\n toString() {\n return this.name + (this.message && ': ') + this.message;\n }\n };\n };\n\n const getUserMedia_ = function(constraints, onSuccess, onError) {\n shimConstraints_(constraints, c => {\n navigator.webkitGetUserMedia(c, onSuccess, e => {\n if (onError) {\n onError(shimError_(e));\n }\n });\n });\n };\n navigator.getUserMedia = getUserMedia_.bind(navigator);\n\n // Even though Chrome 45 has navigator.mediaDevices and a getUserMedia\n // function which returns a Promise, it does not accept spec-style\n // constraints.\n if (navigator.mediaDevices.getUserMedia) {\n const origGetUserMedia = navigator.mediaDevices.getUserMedia.\n bind(navigator.mediaDevices);\n navigator.mediaDevices.getUserMedia = function(cs) {\n return shimConstraints_(cs, c => origGetUserMedia(c).then(stream => {\n if (c.audio && !stream.getAudioTracks().length ||\n c.video && !stream.getVideoTracks().length) {\n stream.getTracks().forEach(track => {\n track.stop();\n });\n throw new DOMException('', 'NotFoundError');\n }\n return stream;\n }, e => Promise.reject(shimError_(e))));\n };\n }\n}\n","/*\n * Copyright (c) 2018 The adapter.js project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n/* eslint-env node */\n'use strict';\nexport function shimGetDisplayMedia(window, getSourceId) {\n if (window.navigator.mediaDevices &&\n 'getDisplayMedia' in window.navigator.mediaDevices) {\n return;\n }\n if (!(window.navigator.mediaDevices)) {\n return;\n }\n // getSourceId is a function that returns a promise resolving with\n // the sourceId of the screen/window/tab to be shared.\n if (typeof getSourceId !== 'function') {\n console.error('shimGetDisplayMedia: getSourceId argument is not ' +\n 'a function');\n return;\n }\n window.navigator.mediaDevices.getDisplayMedia =\n function getDisplayMedia(constraints) {\n return getSourceId(constraints)\n .then(sourceId => {\n const widthSpecified = constraints.video && constraints.video.width;\n const heightSpecified = constraints.video &&\n constraints.video.height;\n const frameRateSpecified = constraints.video &&\n constraints.video.frameRate;\n constraints.video = {\n mandatory: {\n chromeMediaSource: 'desktop',\n chromeMediaSourceId: sourceId,\n maxFrameRate: frameRateSpecified || 3\n }\n };\n if (widthSpecified) {\n constraints.video.mandatory.maxWidth = widthSpecified;\n }\n if (heightSpecified) {\n constraints.video.mandatory.maxHeight = heightSpecified;\n }\n return window.navigator.mediaDevices.getUserMedia(constraints);\n });\n };\n}\n","/*\n * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n /* eslint-env node */\n'use strict';\nimport * as utils from '../utils.js';\n\nexport {shimGetUserMedia} from './getusermedia';\nexport {shimGetDisplayMedia} from './getdisplaymedia';\n\nexport function shimMediaStream(window) {\n window.MediaStream = window.MediaStream || window.webkitMediaStream;\n}\n\nexport function shimOnTrack(window) {\n if (typeof window === 'object' && window.RTCPeerConnection && !('ontrack' in\n window.RTCPeerConnection.prototype)) {\n Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', {\n get() {\n return this._ontrack;\n },\n set(f) {\n if (this._ontrack) {\n this.removeEventListener('track', this._ontrack);\n }\n this.addEventListener('track', this._ontrack = f);\n },\n enumerable: true,\n configurable: true\n });\n const origSetRemoteDescription =\n window.RTCPeerConnection.prototype.setRemoteDescription;\n window.RTCPeerConnection.prototype.setRemoteDescription =\n function setRemoteDescription() {\n if (!this._ontrackpoly) {\n this._ontrackpoly = (e) => {\n // onaddstream does not fire when a track is added to an existing\n // stream. But stream.onaddtrack is implemented so we use that.\n e.stream.addEventListener('addtrack', te => {\n let receiver;\n if (window.RTCPeerConnection.prototype.getReceivers) {\n receiver = this.getReceivers()\n .find(r => r.track && r.track.id === te.track.id);\n } else {\n receiver = {track: te.track};\n }\n\n const event = new Event('track');\n event.track = te.track;\n event.receiver = receiver;\n event.transceiver = {receiver};\n event.streams = [e.stream];\n this.dispatchEvent(event);\n });\n e.stream.getTracks().forEach(track => {\n let receiver;\n if (window.RTCPeerConnection.prototype.getReceivers) {\n receiver = this.getReceivers()\n .find(r => r.track && r.track.id === track.id);\n } else {\n receiver = {track};\n }\n const event = new Event('track');\n event.track = track;\n event.receiver = receiver;\n event.transceiver = {receiver};\n event.streams = [e.stream];\n this.dispatchEvent(event);\n });\n };\n this.addEventListener('addstream', this._ontrackpoly);\n }\n return origSetRemoteDescription.apply(this, arguments);\n };\n } else {\n // even if RTCRtpTransceiver is in window, it is only used and\n // emitted in unified-plan. Unfortunately this means we need\n // to unconditionally wrap the event.\n utils.wrapPeerConnectionEvent(window, 'track', e => {\n if (!e.transceiver) {\n Object.defineProperty(e, 'transceiver',\n {value: {receiver: e.receiver}});\n }\n return e;\n });\n }\n}\n\nexport function shimGetSendersWithDtmf(window) {\n // Overrides addTrack/removeTrack, depends on shimAddTrackRemoveTrack.\n if (typeof window === 'object' && window.RTCPeerConnection &&\n !('getSenders' in window.RTCPeerConnection.prototype) &&\n 'createDTMFSender' in window.RTCPeerConnection.prototype) {\n const shimSenderWithDtmf = function(pc, track) {\n return {\n track,\n get dtmf() {\n if (this._dtmf === undefined) {\n if (track.kind === 'audio') {\n this._dtmf = pc.createDTMFSender(track);\n } else {\n this._dtmf = null;\n }\n }\n return this._dtmf;\n },\n _pc: pc\n };\n };\n\n // augment addTrack when getSenders is not available.\n if (!window.RTCPeerConnection.prototype.getSenders) {\n window.RTCPeerConnection.prototype.getSenders = function getSenders() {\n this._senders = this._senders || [];\n return this._senders.slice(); // return a copy of the internal state.\n };\n const origAddTrack = window.RTCPeerConnection.prototype.addTrack;\n window.RTCPeerConnection.prototype.addTrack =\n function addTrack(track, stream) {\n let sender = origAddTrack.apply(this, arguments);\n if (!sender) {\n sender = shimSenderWithDtmf(this, track);\n this._senders.push(sender);\n }\n return sender;\n };\n\n const origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack;\n window.RTCPeerConnection.prototype.removeTrack =\n function removeTrack(sender) {\n origRemoveTrack.apply(this, arguments);\n const idx = this._senders.indexOf(sender);\n if (idx !== -1) {\n this._senders.splice(idx, 1);\n }\n };\n }\n const origAddStream = window.RTCPeerConnection.prototype.addStream;\n window.RTCPeerConnection.prototype.addStream = function addStream(stream) {\n this._senders = this._senders || [];\n origAddStream.apply(this, [stream]);\n stream.getTracks().forEach(track => {\n this._senders.push(shimSenderWithDtmf(this, track));\n });\n };\n\n const origRemoveStream = window.RTCPeerConnection.prototype.removeStream;\n window.RTCPeerConnection.prototype.removeStream =\n function removeStream(stream) {\n this._senders = this._senders || [];\n origRemoveStream.apply(this, [stream]);\n\n stream.getTracks().forEach(track => {\n const sender = this._senders.find(s => s.track === track);\n if (sender) { // remove sender\n this._senders.splice(this._senders.indexOf(sender), 1);\n }\n });\n };\n } else if (typeof window === 'object' && window.RTCPeerConnection &&\n 'getSenders' in window.RTCPeerConnection.prototype &&\n 'createDTMFSender' in window.RTCPeerConnection.prototype &&\n window.RTCRtpSender &&\n !('dtmf' in window.RTCRtpSender.prototype)) {\n const origGetSenders = window.RTCPeerConnection.prototype.getSenders;\n window.RTCPeerConnection.prototype.getSenders = function getSenders() {\n const senders = origGetSenders.apply(this, []);\n senders.forEach(sender => sender._pc = this);\n return senders;\n };\n\n Object.defineProperty(window.RTCRtpSender.prototype, 'dtmf', {\n get() {\n if (this._dtmf === undefined) {\n if (this.track.kind === 'audio') {\n this._dtmf = this._pc.createDTMFSender(this.track);\n } else {\n this._dtmf = null;\n }\n }\n return this._dtmf;\n }\n });\n }\n}\n\nexport function shimGetStats(window) {\n if (!window.RTCPeerConnection) {\n return;\n }\n\n const origGetStats = window.RTCPeerConnection.prototype.getStats;\n window.RTCPeerConnection.prototype.getStats = function getStats() {\n const [selector, onSucc, onErr] = arguments;\n\n // If selector is a function then we are in the old style stats so just\n // pass back the original getStats format to avoid breaking old users.\n if (arguments.length > 0 && typeof selector === 'function') {\n return origGetStats.apply(this, arguments);\n }\n\n // When spec-style getStats is supported, return those when called with\n // either no arguments or the selector argument is null.\n if (origGetStats.length === 0 && (arguments.length === 0 ||\n typeof selector !== 'function')) {\n return origGetStats.apply(this, []);\n }\n\n const fixChromeStats_ = function(response) {\n const standardReport = {};\n const reports = response.result();\n reports.forEach(report => {\n const standardStats = {\n id: report.id,\n timestamp: report.timestamp,\n type: {\n localcandidate: 'local-candidate',\n remotecandidate: 'remote-candidate'\n }[report.type] || report.type\n };\n report.names().forEach(name => {\n standardStats[name] = report.stat(name);\n });\n standardReport[standardStats.id] = standardStats;\n });\n\n return standardReport;\n };\n\n // shim getStats with maplike support\n const makeMapStats = function(stats) {\n return new Map(Object.keys(stats).map(key => [key, stats[key]]));\n };\n\n if (arguments.length >= 2) {\n const successCallbackWrapper_ = function(response) {\n onSucc(makeMapStats(fixChromeStats_(response)));\n };\n\n return origGetStats.apply(this, [successCallbackWrapper_,\n selector]);\n }\n\n // promise-support\n return new Promise((resolve, reject) => {\n origGetStats.apply(this, [\n function(response) {\n resolve(makeMapStats(fixChromeStats_(response)));\n }, reject]);\n }).then(onSucc, onErr);\n };\n}\n\nexport function shimSenderReceiverGetStats(window) {\n if (!(typeof window === 'object' && window.RTCPeerConnection &&\n window.RTCRtpSender && window.RTCRtpReceiver)) {\n return;\n }\n\n // shim sender stats.\n if (!('getStats' in window.RTCRtpSender.prototype)) {\n const origGetSenders = window.RTCPeerConnection.prototype.getSenders;\n if (origGetSenders) {\n window.RTCPeerConnection.prototype.getSenders = function getSenders() {\n const senders = origGetSenders.apply(this, []);\n senders.forEach(sender => sender._pc = this);\n return senders;\n };\n }\n\n const origAddTrack = window.RTCPeerConnection.prototype.addTrack;\n if (origAddTrack) {\n window.RTCPeerConnection.prototype.addTrack = function addTrack() {\n const sender = origAddTrack.apply(this, arguments);\n sender._pc = this;\n return sender;\n };\n }\n window.RTCRtpSender.prototype.getStats = function getStats() {\n const sender = this;\n return this._pc.getStats().then(result =>\n /* Note: this will include stats of all senders that\n * send a track with the same id as sender.track as\n * it is not possible to identify the RTCRtpSender.\n */\n utils.filterStats(result, sender.track, true));\n };\n }\n\n // shim receiver stats.\n if (!('getStats' in window.RTCRtpReceiver.prototype)) {\n const origGetReceivers = window.RTCPeerConnection.prototype.getReceivers;\n if (origGetReceivers) {\n window.RTCPeerConnection.prototype.getReceivers =\n function getReceivers() {\n const receivers = origGetReceivers.apply(this, []);\n receivers.forEach(receiver => receiver._pc = this);\n return receivers;\n };\n }\n utils.wrapPeerConnectionEvent(window, 'track', e => {\n e.receiver._pc = e.srcElement;\n return e;\n });\n window.RTCRtpReceiver.prototype.getStats = function getStats() {\n const receiver = this;\n return this._pc.getStats().then(result =>\n utils.filterStats(result, receiver.track, false));\n };\n }\n\n if (!('getStats' in window.RTCRtpSender.prototype &&\n 'getStats' in window.RTCRtpReceiver.prototype)) {\n return;\n }\n\n // shim RTCPeerConnection.getStats(track).\n const origGetStats = window.RTCPeerConnection.prototype.getStats;\n window.RTCPeerConnection.prototype.getStats = function getStats() {\n if (arguments.length > 0 &&\n arguments[0] instanceof window.MediaStreamTrack) {\n const track = arguments[0];\n let sender;\n let receiver;\n let err;\n this.getSenders().forEach(s => {\n if (s.track === track) {\n if (sender) {\n err = true;\n } else {\n sender = s;\n }\n }\n });\n this.getReceivers().forEach(r => {\n if (r.track === track) {\n if (receiver) {\n err = true;\n } else {\n receiver = r;\n }\n }\n return r.track === track;\n });\n if (err || (sender && receiver)) {\n return Promise.reject(new DOMException(\n 'There are more than one sender or receiver for the track.',\n 'InvalidAccessError'));\n } else if (sender) {\n return sender.getStats();\n } else if (receiver) {\n return receiver.getStats();\n }\n return Promise.reject(new DOMException(\n 'There is no sender or receiver for the track.',\n 'InvalidAccessError'));\n }\n return origGetStats.apply(this, arguments);\n };\n}\n\nexport function shimAddTrackRemoveTrackWithNative(window) {\n // shim addTrack/removeTrack with native variants in order to make\n // the interactions with legacy getLocalStreams behave as in other browsers.\n // Keeps a mapping stream.id => [stream, rtpsenders...]\n window.RTCPeerConnection.prototype.getLocalStreams =\n function getLocalStreams() {\n this._shimmedLocalStreams = this._shimmedLocalStreams || {};\n return Object.keys(this._shimmedLocalStreams)\n .map(streamId => this._shimmedLocalStreams[streamId][0]);\n };\n\n const origAddTrack = window.RTCPeerConnection.prototype.addTrack;\n window.RTCPeerConnection.prototype.addTrack =\n function addTrack(track, stream) {\n if (!stream) {\n return origAddTrack.apply(this, arguments);\n }\n this._shimmedLocalStreams = this._shimmedLocalStreams || {};\n\n const sender = origAddTrack.apply(this, arguments);\n if (!this._shimmedLocalStreams[stream.id]) {\n this._shimmedLocalStreams[stream.id] = [stream, sender];\n } else if (this._shimmedLocalStreams[stream.id].indexOf(sender) === -1) {\n this._shimmedLocalStreams[stream.id].push(sender);\n }\n return sender;\n };\n\n const origAddStream = window.RTCPeerConnection.prototype.addStream;\n window.RTCPeerConnection.prototype.addStream = function addStream(stream) {\n this._shimmedLocalStreams = this._shimmedLocalStreams || {};\n\n stream.getTracks().forEach(track => {\n const alreadyExists = this.getSenders().find(s => s.track === track);\n if (alreadyExists) {\n throw new DOMException('Track already exists.',\n 'InvalidAccessError');\n }\n });\n const existingSenders = this.getSenders();\n origAddStream.apply(this, arguments);\n const newSenders = this.getSenders()\n .filter(newSender => existingSenders.indexOf(newSender) === -1);\n this._shimmedLocalStreams[stream.id] = [stream].concat(newSenders);\n };\n\n const origRemoveStream = window.RTCPeerConnection.prototype.removeStream;\n window.RTCPeerConnection.prototype.removeStream =\n function removeStream(stream) {\n this._shimmedLocalStreams = this._shimmedLocalStreams || {};\n delete this._shimmedLocalStreams[stream.id];\n return origRemoveStream.apply(this, arguments);\n };\n\n const origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack;\n window.RTCPeerConnection.prototype.removeTrack =\n function removeTrack(sender) {\n this._shimmedLocalStreams = this._shimmedLocalStreams || {};\n if (sender) {\n Object.keys(this._shimmedLocalStreams).forEach(streamId => {\n const idx = this._shimmedLocalStreams[streamId].indexOf(sender);\n if (idx !== -1) {\n this._shimmedLocalStreams[streamId].splice(idx, 1);\n }\n if (this._shimmedLocalStreams[streamId].length === 1) {\n delete this._shimmedLocalStreams[streamId];\n }\n });\n }\n return origRemoveTrack.apply(this, arguments);\n };\n}\n\nexport function shimAddTrackRemoveTrack(window, browserDetails) {\n if (!window.RTCPeerConnection) {\n return;\n }\n // shim addTrack and removeTrack.\n if (window.RTCPeerConnection.prototype.addTrack &&\n browserDetails.version >= 65) {\n return shimAddTrackRemoveTrackWithNative(window);\n }\n\n // also shim pc.getLocalStreams when addTrack is shimmed\n // to return the original streams.\n const origGetLocalStreams = window.RTCPeerConnection.prototype\n .getLocalStreams;\n window.RTCPeerConnection.prototype.getLocalStreams =\n function getLocalStreams() {\n const nativeStreams = origGetLocalStreams.apply(this);\n this._reverseStreams = this._reverseStreams || {};\n return nativeStreams.map(stream => this._reverseStreams[stream.id]);\n };\n\n const origAddStream = window.RTCPeerConnection.prototype.addStream;\n window.RTCPeerConnection.prototype.addStream = function addStream(stream) {\n this._streams = this._streams || {};\n this._reverseStreams = this._reverseStreams || {};\n\n stream.getTracks().forEach(track => {\n const alreadyExists = this.getSenders().find(s => s.track === track);\n if (alreadyExists) {\n throw new DOMException('Track already exists.',\n 'InvalidAccessError');\n }\n });\n // Add identity mapping for consistency with addTrack.\n // Unless this is being used with a stream from addTrack.\n if (!this._reverseStreams[stream.id]) {\n const newStream = new window.MediaStream(stream.getTracks());\n this._streams[stream.id] = newStream;\n this._reverseStreams[newStream.id] = stream;\n stream = newStream;\n }\n origAddStream.apply(this, [stream]);\n };\n\n const origRemoveStream = window.RTCPeerConnection.prototype.removeStream;\n window.RTCPeerConnection.prototype.removeStream =\n function removeStream(stream) {\n this._streams = this._streams || {};\n this._reverseStreams = this._reverseStreams || {};\n\n origRemoveStream.apply(this, [(this._streams[stream.id] || stream)]);\n delete this._reverseStreams[(this._streams[stream.id] ?\n this._streams[stream.id].id : stream.id)];\n delete this._streams[stream.id];\n };\n\n window.RTCPeerConnection.prototype.addTrack =\n function addTrack(track, stream) {\n if (this.signalingState === 'closed') {\n throw new DOMException(\n 'The RTCPeerConnection\\'s signalingState is \\'closed\\'.',\n 'InvalidStateError');\n }\n const streams = [].slice.call(arguments, 1);\n if (streams.length !== 1 ||\n !streams[0].getTracks().find(t => t === track)) {\n // this is not fully correct but all we can manage without\n // [[associated MediaStreams]] internal slot.\n throw new DOMException(\n 'The adapter.js addTrack polyfill only supports a single ' +\n ' stream which is associated with the specified track.',\n 'NotSupportedError');\n }\n\n const alreadyExists = this.getSenders().find(s => s.track === track);\n if (alreadyExists) {\n throw new DOMException('Track already exists.',\n 'InvalidAccessError');\n }\n\n this._streams = this._streams || {};\n this._reverseStreams = this._reverseStreams || {};\n const oldStream = this._streams[stream.id];\n if (oldStream) {\n // this is using odd Chrome behaviour, use with caution:\n // https://bugs.chromium.org/p/webrtc/issues/detail?id=7815\n // Note: we rely on the high-level addTrack/dtmf shim to\n // create the sender with a dtmf sender.\n oldStream.addTrack(track);\n\n // Trigger ONN async.\n Promise.resolve().then(() => {\n this.dispatchEvent(new Event('negotiationneeded'));\n });\n } else {\n const newStream = new window.MediaStream([track]);\n this._streams[stream.id] = newStream;\n this._reverseStreams[newStream.id] = stream;\n this.addStream(newStream);\n }\n return this.getSenders().find(s => s.track === track);\n };\n\n // replace the internal stream id with the external one and\n // vice versa.\n function replaceInternalStreamId(pc, description) {\n let sdp = description.sdp;\n Object.keys(pc._reverseStreams || []).forEach(internalId => {\n const externalStream = pc._reverseStreams[internalId];\n const internalStream = pc._streams[externalStream.id];\n sdp = sdp.replace(new RegExp(internalStream.id, 'g'),\n externalStream.id);\n });\n return new RTCSessionDescription({\n type: description.type,\n sdp\n });\n }\n function replaceExternalStreamId(pc, description) {\n let sdp = description.sdp;\n Object.keys(pc._reverseStreams || []).forEach(internalId => {\n const externalStream = pc._reverseStreams[internalId];\n const internalStream = pc._streams[externalStream.id];\n sdp = sdp.replace(new RegExp(externalStream.id, 'g'),\n internalStream.id);\n });\n return new RTCSessionDescription({\n type: description.type,\n sdp\n });\n }\n ['createOffer', 'createAnswer'].forEach(function(method) {\n const nativeMethod = window.RTCPeerConnection.prototype[method];\n const methodObj = {[method]() {\n const args = arguments;\n const isLegacyCall = arguments.length &&\n typeof arguments[0] === 'function';\n if (isLegacyCall) {\n return nativeMethod.apply(this, [\n (description) => {\n const desc = replaceInternalStreamId(this, description);\n args[0].apply(null, [desc]);\n },\n (err) => {\n if (args[1]) {\n args[1].apply(null, err);\n }\n }, arguments[2]\n ]);\n }\n return nativeMethod.apply(this, arguments)\n .then(description => replaceInternalStreamId(this, description));\n }};\n window.RTCPeerConnection.prototype[method] = methodObj[method];\n });\n\n const origSetLocalDescription =\n window.RTCPeerConnection.prototype.setLocalDescription;\n window.RTCPeerConnection.prototype.setLocalDescription =\n function setLocalDescription() {\n if (!arguments.length || !arguments[0].type) {\n return origSetLocalDescription.apply(this, arguments);\n }\n arguments[0] = replaceExternalStreamId(this, arguments[0]);\n return origSetLocalDescription.apply(this, arguments);\n };\n\n // TODO: mangle getStats: https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamstats-streamidentifier\n\n const origLocalDescription = Object.getOwnPropertyDescriptor(\n window.RTCPeerConnection.prototype, 'localDescription');\n Object.defineProperty(window.RTCPeerConnection.prototype,\n 'localDescription', {\n get() {\n const description = origLocalDescription.get.apply(this);\n if (description.type === '') {\n return description;\n }\n return replaceInternalStreamId(this, description);\n }\n });\n\n window.RTCPeerConnection.prototype.removeTrack =\n function removeTrack(sender) {\n if (this.signalingState === 'closed') {\n throw new DOMException(\n 'The RTCPeerConnection\\'s signalingState is \\'closed\\'.',\n 'InvalidStateError');\n }\n // We can not yet check for sender instanceof RTCRtpSender\n // since we shim RTPSender. So we check if sender._pc is set.\n if (!sender._pc) {\n throw new DOMException('Argument 1 of RTCPeerConnection.removeTrack ' +\n 'does not implement interface RTCRtpSender.', 'TypeError');\n }\n const isLocal = sender._pc === this;\n if (!isLocal) {\n throw new DOMException('Sender was not created by this connection.',\n 'InvalidAccessError');\n }\n\n // Search for the native stream the senders track belongs to.\n this._streams = this._streams || {};\n let stream;\n Object.keys(this._streams).forEach(streamid => {\n const hasTrack = this._streams[streamid].getTracks()\n .find(track => sender.track === track);\n if (hasTrack) {\n stream = this._streams[streamid];\n }\n });\n\n if (stream) {\n if (stream.getTracks().length === 1) {\n // if this is the last track of the stream, remove the stream. This\n // takes care of any shimmed _senders.\n this.removeStream(this._reverseStreams[stream.id]);\n } else {\n // relying on the same odd chrome behaviour as above.\n stream.removeTrack(sender.track);\n }\n this.dispatchEvent(new Event('negotiationneeded'));\n }\n };\n}\n\nexport function shimPeerConnection(window, browserDetails) {\n if (!window.RTCPeerConnection && window.webkitRTCPeerConnection) {\n // very basic support for old versions.\n window.RTCPeerConnection = window.webkitRTCPeerConnection;\n }\n if (!window.RTCPeerConnection) {\n return;\n }\n\n // shim implicit creation of RTCSessionDescription/RTCIceCandidate\n if (browserDetails.version < 53) {\n ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']\n .forEach(function(method) {\n const nativeMethod = window.RTCPeerConnection.prototype[method];\n const methodObj = {[method]() {\n arguments[0] = new ((method === 'addIceCandidate') ?\n window.RTCIceCandidate :\n window.RTCSessionDescription)(arguments[0]);\n return nativeMethod.apply(this, arguments);\n }};\n window.RTCPeerConnection.prototype[method] = methodObj[method];\n });\n }\n}\n\n// Attempt to fix ONN in plan-b mode.\nexport function fixNegotiationNeeded(window, browserDetails) {\n utils.wrapPeerConnectionEvent(window, 'negotiationneeded', e => {\n const pc = e.target;\n if (browserDetails.version < 72 || (pc.getConfiguration &&\n pc.getConfiguration().sdpSemantics === 'plan-b')) {\n if (pc.signalingState !== 'stable') {\n return;\n }\n }\n return e;\n });\n}\n","/*\n * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n/* eslint-env node */\n'use strict';\n\nimport * as utils from '../utils';\n// Edge does not like\n// 1) stun: filtered after 14393 unless ?transport=udp is present\n// 2) turn: that does not have all of turn:host:port?transport=udp\n// 3) turn: with ipv6 addresses\n// 4) turn: occurring muliple times\nexport function filterIceServers(iceServers, edgeVersion) {\n let hasTurn = false;\n iceServers = JSON.parse(JSON.stringify(iceServers));\n return iceServers.filter(server => {\n if (server && (server.urls || server.url)) {\n let urls = server.urls || server.url;\n if (server.url && !server.urls) {\n utils.deprecated('RTCIceServer.url', 'RTCIceServer.urls');\n }\n const isString = typeof urls === 'string';\n if (isString) {\n urls = [urls];\n }\n urls = urls.filter(url => {\n // filter STUN unconditionally.\n if (url.indexOf('stun:') === 0) {\n return false;\n }\n\n const validTurn = url.startsWith('turn') &&\n !url.startsWith('turn:[') &&\n url.includes('transport=udp');\n if (validTurn && !hasTurn) {\n hasTurn = true;\n return true;\n }\n return validTurn && !hasTurn;\n });\n\n delete server.url;\n server.urls = isString ? urls[0] : urls;\n return !!urls.length;\n }\n });\n}\n","/* eslint-env node */\n'use strict';\n\n// SDP helpers.\nvar SDPUtils = {};\n\n// Generate an alphanumeric identifier for cname or mids.\n// TODO: use UUIDs instead? https://gist.github.com/jed/982883\nSDPUtils.generateIdentifier = function() {\n return Math.random().toString(36).substr(2, 10);\n};\n\n// The RTCP CNAME used by all peerconnections from the same JS.\nSDPUtils.localCName = SDPUtils.generateIdentifier();\n\n// Splits SDP into lines, dealing with both CRLF and LF.\nSDPUtils.splitLines = function(blob) {\n return blob.trim().split('\\n').map(function(line) {\n return line.trim();\n });\n};\n// Splits SDP into sessionpart and mediasections. Ensures CRLF.\nSDPUtils.splitSections = function(blob) {\n var parts = blob.split('\\nm=');\n return parts.map(function(part, index) {\n return (index > 0 ? 'm=' + part : part).trim() + '\\r\\n';\n });\n};\n\n// returns the session description.\nSDPUtils.getDescription = function(blob) {\n var sections = SDPUtils.splitSections(blob);\n return sections && sections[0];\n};\n\n// returns the individual media sections.\nSDPUtils.getMediaSections = function(blob) {\n var sections = SDPUtils.splitSections(blob);\n sections.shift();\n return sections;\n};\n\n// Returns lines that start with a certain prefix.\nSDPUtils.matchPrefix = function(blob, prefix) {\n return SDPUtils.splitLines(blob).filter(function(line) {\n return line.indexOf(prefix) === 0;\n });\n};\n\n// Parses an ICE candidate line. Sample input:\n// candidate:702786350 2 udp 41819902 8.8.8.8 60769 typ relay raddr 8.8.8.8\n// rport 55996\"\nSDPUtils.parseCandidate = function(line) {\n var parts;\n // Parse both variants.\n if (line.indexOf('a=candidate:') === 0) {\n parts = line.substring(12).split(' ');\n } else {\n parts = line.substring(10).split(' ');\n }\n\n var candidate = {\n foundation: parts[0],\n component: parseInt(parts[1], 10),\n protocol: parts[2].toLowerCase(),\n priority: parseInt(parts[3], 10),\n ip: parts[4],\n address: parts[4], // address is an alias for ip.\n port: parseInt(parts[5], 10),\n // skip parts[6] == 'typ'\n type: parts[7]\n };\n\n for (var i = 8; i < parts.length; i += 2) {\n switch (parts[i]) {\n case 'raddr':\n candidate.relatedAddress = parts[i + 1];\n break;\n case 'rport':\n candidate.relatedPort = parseInt(parts[i + 1], 10);\n break;\n case 'tcptype':\n candidate.tcpType = parts[i + 1];\n break;\n case 'ufrag':\n candidate.ufrag = parts[i + 1]; // for backward compability.\n candidate.usernameFragment = parts[i + 1];\n break;\n default: // extension handling, in particular ufrag\n candidate[parts[i]] = parts[i + 1];\n break;\n }\n }\n return candidate;\n};\n\n// Translates a candidate object into SDP candidate attribute.\nSDPUtils.writeCandidate = function(candidate) {\n var sdp = [];\n sdp.push(candidate.foundation);\n sdp.push(candidate.component);\n sdp.push(candidate.protocol.toUpperCase());\n sdp.push(candidate.priority);\n sdp.push(candidate.address || candidate.ip);\n sdp.push(candidate.port);\n\n var type = candidate.type;\n sdp.push('typ');\n sdp.push(type);\n if (type !== 'host' && candidate.relatedAddress &&\n candidate.relatedPort) {\n sdp.push('raddr');\n sdp.push(candidate.relatedAddress);\n sdp.push('rport');\n sdp.push(candidate.relatedPort);\n }\n if (candidate.tcpType && candidate.protocol.toLowerCase() === 'tcp') {\n sdp.push('tcptype');\n sdp.push(candidate.tcpType);\n }\n if (candidate.usernameFragment || candidate.ufrag) {\n sdp.push('ufrag');\n sdp.push(candidate.usernameFragment || candidate.ufrag);\n }\n return 'candidate:' + sdp.join(' ');\n};\n\n// Parses an ice-options line, returns an array of option tags.\n// a=ice-options:foo bar\nSDPUtils.parseIceOptions = function(line) {\n return line.substr(14).split(' ');\n};\n\n// Parses an rtpmap line, returns RTCRtpCoddecParameters. Sample input:\n// a=rtpmap:111 opus/48000/2\nSDPUtils.parseRtpMap = function(line) {\n var parts = line.substr(9).split(' ');\n var parsed = {\n payloadType: parseInt(parts.shift(), 10) // was: id\n };\n\n parts = parts[0].split('/');\n\n parsed.name = parts[0];\n parsed.clockRate = parseInt(parts[1], 10); // was: clockrate\n parsed.channels = parts.length === 3 ? parseInt(parts[2], 10) : 1;\n // legacy alias, got renamed back to channels in ORTC.\n parsed.numChannels = parsed.channels;\n return parsed;\n};\n\n// Generate an a=rtpmap line from RTCRtpCodecCapability or\n// RTCRtpCodecParameters.\nSDPUtils.writeRtpMap = function(codec) {\n var pt = codec.payloadType;\n if (codec.preferredPayloadType !== undefined) {\n pt = codec.preferredPayloadType;\n }\n var channels = codec.channels || codec.numChannels || 1;\n return 'a=rtpmap:' + pt + ' ' + codec.name + '/' + codec.clockRate +\n (channels !== 1 ? '/' + channels : '') + '\\r\\n';\n};\n\n// Parses an a=extmap line (headerextension from RFC 5285). Sample input:\n// a=extmap:2 urn:ietf:params:rtp-hdrext:toffset\n// a=extmap:2/sendonly urn:ietf:params:rtp-hdrext:toffset\nSDPUtils.parseExtmap = function(line) {\n var parts = line.substr(9).split(' ');\n return {\n id: parseInt(parts[0], 10),\n direction: parts[0].indexOf('/') > 0 ? parts[0].split('/')[1] : 'sendrecv',\n uri: parts[1]\n };\n};\n\n// Generates a=extmap line from RTCRtpHeaderExtensionParameters or\n// RTCRtpHeaderExtension.\nSDPUtils.writeExtmap = function(headerExtension) {\n return 'a=extmap:' + (headerExtension.id || headerExtension.preferredId) +\n (headerExtension.direction && headerExtension.direction !== 'sendrecv'\n ? '/' + headerExtension.direction\n : '') +\n ' ' + headerExtension.uri + '\\r\\n';\n};\n\n// Parses an ftmp line, returns dictionary. Sample input:\n// a=fmtp:96 vbr=on;cng=on\n// Also deals with vbr=on; cng=on\nSDPUtils.parseFmtp = function(line) {\n var parsed = {};\n var kv;\n var parts = line.substr(line.indexOf(' ') + 1).split(';');\n for (var j = 0; j < parts.length; j++) {\n kv = parts[j].trim().split('=');\n parsed[kv[0].trim()] = kv[1];\n }\n return parsed;\n};\n\n// Generates an a=ftmp line from RTCRtpCodecCapability or RTCRtpCodecParameters.\nSDPUtils.writeFmtp = function(codec) {\n var line = '';\n var pt = codec.payloadType;\n if (codec.preferredPayloadType !== undefined) {\n pt = codec.preferredPayloadType;\n }\n if (codec.parameters && Object.keys(codec.parameters).length) {\n var params = [];\n Object.keys(codec.parameters).forEach(function(param) {\n if (codec.parameters[param]) {\n params.push(param + '=' + codec.parameters[param]);\n } else {\n params.push(param);\n }\n });\n line += 'a=fmtp:' + pt + ' ' + params.join(';') + '\\r\\n';\n }\n return line;\n};\n\n// Parses an rtcp-fb line, returns RTCPRtcpFeedback object. Sample input:\n// a=rtcp-fb:98 nack rpsi\nSDPUtils.parseRtcpFb = function(line) {\n var parts = line.substr(line.indexOf(' ') + 1).split(' ');\n return {\n type: parts.shift(),\n parameter: parts.join(' ')\n };\n};\n// Generate a=rtcp-fb lines from RTCRtpCodecCapability or RTCRtpCodecParameters.\nSDPUtils.writeRtcpFb = function(codec) {\n var lines = '';\n var pt = codec.payloadType;\n if (codec.preferredPayloadType !== undefined) {\n pt = codec.preferredPayloadType;\n }\n if (codec.rtcpFeedback && codec.rtcpFeedback.length) {\n // FIXME: special handling for trr-int?\n codec.rtcpFeedback.forEach(function(fb) {\n lines += 'a=rtcp-fb:' + pt + ' ' + fb.type +\n (fb.parameter && fb.parameter.length ? ' ' + fb.parameter : '') +\n '\\r\\n';\n });\n }\n return lines;\n};\n\n// Parses an RFC 5576 ssrc media attribute. Sample input:\n// a=ssrc:3735928559 cname:something\nSDPUtils.parseSsrcMedia = function(line) {\n var sp = line.indexOf(' ');\n var parts = {\n ssrc: parseInt(line.substr(7, sp - 7), 10)\n };\n var colon = line.indexOf(':', sp);\n if (colon > -1) {\n parts.attribute = line.substr(sp + 1, colon - sp - 1);\n parts.value = line.substr(colon + 1);\n } else {\n parts.attribute = line.substr(sp + 1);\n }\n return parts;\n};\n\nSDPUtils.parseSsrcGroup = function(line) {\n var parts = line.substr(13).split(' ');\n return {\n semantics: parts.shift(),\n ssrcs: parts.map(function(ssrc) {\n return parseInt(ssrc, 10);\n })\n };\n};\n\n// Extracts the MID (RFC 5888) from a media section.\n// returns the MID or undefined if no mid line was found.\nSDPUtils.getMid = function(mediaSection) {\n var mid = SDPUtils.matchPrefix(mediaSection, 'a=mid:')[0];\n if (mid) {\n return mid.substr(6);\n }\n};\n\nSDPUtils.parseFingerprint = function(line) {\n var parts = line.substr(14).split(' ');\n return {\n algorithm: parts[0].toLowerCase(), // algorithm is case-sensitive in Edge.\n value: parts[1]\n };\n};\n\n// Extracts DTLS parameters from SDP media section or sessionpart.\n// FIXME: for consistency with other functions this should only\n// get the fingerprint line as input. See also getIceParameters.\nSDPUtils.getDtlsParameters = function(mediaSection, sessionpart) {\n var lines = SDPUtils.matchPrefix(mediaSection + sessionpart,\n 'a=fingerprint:');\n // Note: a=setup line is ignored since we use the 'auto' role.\n // Note2: 'algorithm' is not case sensitive except in Edge.\n return {\n role: 'auto',\n fingerprints: lines.map(SDPUtils.parseFingerprint)\n };\n};\n\n// Serializes DTLS parameters to SDP.\nSDPUtils.writeDtlsParameters = function(params, setupType) {\n var sdp = 'a=setup:' + setupType + '\\r\\n';\n params.fingerprints.forEach(function(fp) {\n sdp += 'a=fingerprint:' + fp.algorithm + ' ' + fp.value + '\\r\\n';\n });\n return sdp;\n};\n\n// Parses a=crypto lines into\n// https://rawgit.com/aboba/edgertc/master/msortc-rs4.html#dictionary-rtcsrtpsdesparameters-members\nSDPUtils.parseCryptoLine = function(line) {\n var parts = line.substr(9).split(' ');\n return {\n tag: parseInt(parts[0], 10),\n cryptoSuite: parts[1],\n keyParams: parts[2],\n sessionParams: parts.slice(3),\n };\n};\n\nSDPUtils.writeCryptoLine = function(parameters) {\n return 'a=crypto:' + parameters.tag + ' ' +\n parameters.cryptoSuite + ' ' +\n (typeof parameters.keyParams === 'object'\n ? SDPUtils.writeCryptoKeyParams(parameters.keyParams)\n : parameters.keyParams) +\n (parameters.sessionParams ? ' ' + parameters.sessionParams.join(' ') : '') +\n '\\r\\n';\n};\n\n// Parses the crypto key parameters into\n// https://rawgit.com/aboba/edgertc/master/msortc-rs4.html#rtcsrtpkeyparam*\nSDPUtils.parseCryptoKeyParams = function(keyParams) {\n if (keyParams.indexOf('inline:') !== 0) {\n return null;\n }\n var parts = keyParams.substr(7).split('|');\n return {\n keyMethod: 'inline',\n keySalt: parts[0],\n lifeTime: parts[1],\n mkiValue: parts[2] ? parts[2].split(':')[0] : undefined,\n mkiLength: parts[2] ? parts[2].split(':')[1] : undefined,\n };\n};\n\nSDPUtils.writeCryptoKeyParams = function(keyParams) {\n return keyParams.keyMethod + ':'\n + keyParams.keySalt +\n (keyParams.lifeTime ? '|' + keyParams.lifeTime : '') +\n (keyParams.mkiValue && keyParams.mkiLength\n ? '|' + keyParams.mkiValue + ':' + keyParams.mkiLength\n : '');\n};\n\n// Extracts all SDES paramters.\nSDPUtils.getCryptoParameters = function(mediaSection, sessionpart) {\n var lines = SDPUtils.matchPrefix(mediaSection + sessionpart,\n 'a=crypto:');\n return lines.map(SDPUtils.parseCryptoLine);\n};\n\n// Parses ICE information from SDP media section or sessionpart.\n// FIXME: for consistency with other functions this should only\n// get the ice-ufrag and ice-pwd lines as input.\nSDPUtils.getIceParameters = function(mediaSection, sessionpart) {\n var ufrag = SDPUtils.matchPrefix(mediaSection + sessionpart,\n 'a=ice-ufrag:')[0];\n var pwd = SDPUtils.matchPrefix(mediaSection + sessionpart,\n 'a=ice-pwd:')[0];\n if (!(ufrag && pwd)) {\n return null;\n }\n return {\n usernameFragment: ufrag.substr(12),\n password: pwd.substr(10),\n };\n};\n\n// Serializes ICE parameters to SDP.\nSDPUtils.writeIceParameters = function(params) {\n return 'a=ice-ufrag:' + params.usernameFragment + '\\r\\n' +\n 'a=ice-pwd:' + params.password + '\\r\\n';\n};\n\n// Parses the SDP media section and returns RTCRtpParameters.\nSDPUtils.parseRtpParameters = function(mediaSection) {\n var description = {\n codecs: [],\n headerExtensions: [],\n fecMechanisms: [],\n rtcp: []\n };\n var lines = SDPUtils.splitLines(mediaSection);\n var mline = lines[0].split(' ');\n for (var i = 3; i < mline.length; i++) { // find all codecs from mline[3..]\n var pt = mline[i];\n var rtpmapline = SDPUtils.matchPrefix(\n mediaSection, 'a=rtpmap:' + pt + ' ')[0];\n if (rtpmapline) {\n var codec = SDPUtils.parseRtpMap(rtpmapline);\n var fmtps = SDPUtils.matchPrefix(\n mediaSection, 'a=fmtp:' + pt + ' ');\n // Only the first a=fmtp:<pt> is considered.\n codec.parameters = fmtps.length ? SDPUtils.parseFmtp(fmtps[0]) : {};\n codec.rtcpFeedback = SDPUtils.matchPrefix(\n mediaSection, 'a=rtcp-fb:' + pt + ' ')\n .map(SDPUtils.parseRtcpFb);\n description.codecs.push(codec);\n // parse FEC mechanisms from rtpmap lines.\n switch (codec.name.toUpperCase()) {\n case 'RED':\n case 'ULPFEC':\n description.fecMechanisms.push(codec.name.toUpperCase());\n break;\n default: // only RED and ULPFEC are recognized as FEC mechanisms.\n break;\n }\n }\n }\n SDPUtils.matchPrefix(mediaSection, 'a=extmap:').forEach(function(line) {\n description.headerExtensions.push(SDPUtils.parseExtmap(line));\n });\n // FIXME: parse rtcp.\n return description;\n};\n\n// Generates parts of the SDP media section describing the capabilities /\n// parameters.\nSDPUtils.writeRtpDescription = function(kind, caps) {\n var sdp = '';\n\n // Build the mline.\n sdp += 'm=' + kind + ' ';\n sdp += caps.codecs.length > 0 ? '9' : '0'; // reject if no codecs.\n sdp += ' UDP/TLS/RTP/SAVPF ';\n sdp += caps.codecs.map(function(codec) {\n if (codec.preferredPayloadType !== undefined) {\n return codec.preferredPayloadType;\n }\n return codec.payloadType;\n }).join(' ') + '\\r\\n';\n\n sdp += 'c=IN IP4 0.0.0.0\\r\\n';\n sdp += 'a=rtcp:9 IN IP4 0.0.0.0\\r\\n';\n\n // Add a=rtpmap lines for each codec. Also fmtp and rtcp-fb.\n caps.codecs.forEach(function(codec) {\n sdp += SDPUtils.writeRtpMap(codec);\n sdp += SDPUtils.writeFmtp(codec);\n sdp += SDPUtils.writeRtcpFb(codec);\n });\n var maxptime = 0;\n caps.codecs.forEach(function(codec) {\n if (codec.maxptime > maxptime) {\n maxptime = codec.maxptime;\n }\n });\n if (maxptime > 0) {\n sdp += 'a=maxptime:' + maxptime + '\\r\\n';\n }\n sdp += 'a=rtcp-mux\\r\\n';\n\n if (caps.headerExtensions) {\n caps.headerExtensions.forEach(function(extension) {\n sdp += SDPUtils.writeExtmap(extension);\n });\n }\n // FIXME: write fecMechanisms.\n return sdp;\n};\n\n// Parses the SDP media section and returns an array of\n// RTCRtpEncodingParameters.\nSDPUtils.parseRtpEncodingParameters = function(mediaSection) {\n var encodingParameters = [];\n var description = SDPUtils.parseRtpParameters(mediaSection);\n var hasRed = description.fecMechanisms.indexOf('RED') !== -1;\n var hasUlpfec = description.fecMechanisms.indexOf('ULPFEC') !== -1;\n\n // filter a=ssrc:... cname:, ignore PlanB-msid\n var ssrcs = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')\n .map(function(line) {\n return SDPUtils.parseSsrcMedia(line);\n })\n .filter(function(parts) {\n return parts.attribute === 'cname';\n });\n var primarySsrc = ssrcs.length > 0 && ssrcs[0].ssrc;\n var secondarySsrc;\n\n var flows = SDPUtils.matchPrefix(mediaSection, 'a=ssrc-group:FID')\n .map(function(line) {\n var parts = line.substr(17).split(' ');\n return parts.map(function(part) {\n return parseInt(part, 10);\n });\n });\n if (flows.length > 0 && flows[0].length > 1 && flows[0][0] === primarySsrc) {\n secondarySsrc = flows[0][1];\n }\n\n description.codecs.forEach(function(codec) {\n if (codec.name.toUpperCase() === 'RTX' && codec.parameters.apt) {\n var encParam = {\n ssrc: primarySsrc,\n codecPayloadType: parseInt(codec.parameters.apt, 10)\n };\n if (primarySsrc && secondarySsrc) {\n encParam.rtx = {ssrc: secondarySsrc};\n }\n encodingParameters.push(encParam);\n if (hasRed) {\n encParam = JSON.parse(JSON.stringify(encParam));\n encParam.fec = {\n ssrc: primarySsrc,\n mechanism: hasUlpfec ? 'red+ulpfec' : 'red'\n };\n encodingParameters.push(encParam);\n }\n }\n });\n if (encodingParameters.length === 0 && primarySsrc) {\n encodingParameters.push({\n ssrc: primarySsrc\n });\n }\n\n // we support both b=AS and b=TIAS but interpret AS as TIAS.\n var bandwidth = SDPUtils.matchPrefix(mediaSection, 'b=');\n if (bandwidth.length) {\n if (bandwidth[0].indexOf('b=TIAS:') === 0) {\n bandwidth = parseInt(bandwidth[0].substr(7), 10);\n } else if (bandwidth[0].indexOf('b=AS:') === 0) {\n // use formula from JSEP to convert b=AS to TIAS value.\n bandwidth = parseInt(bandwidth[0].substr(5), 10) * 1000 * 0.95\n - (50 * 40 * 8);\n } else {\n bandwidth = undefined;\n }\n encodingParameters.forEach(function(params) {\n params.maxBitrate = bandwidth;\n });\n }\n return encodingParameters;\n};\n\n// parses http://draft.ortc.org/#rtcrtcpparameters*\nSDPUtils.parseRtcpParameters = function(mediaSection) {\n var rtcpParameters = {};\n\n // Gets the first SSRC. Note tha with RTX there might be multiple\n // SSRCs.\n var remoteSsrc = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')\n .map(function(line) {\n return SDPUtils.parseSsrcMedia(line);\n })\n .filter(function(obj) {\n return obj.attribute === 'cname';\n })[0];\n if (remoteSsrc) {\n rtcpParameters.cname = remoteSsrc.value;\n rtcpParameters.ssrc = remoteSsrc.ssrc;\n }\n\n // Edge uses the compound attribute instead of reducedSize\n // compound is !reducedSize\n var rsize = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-rsize');\n rtcpParameters.reducedSize = rsize.length > 0;\n rtcpParameters.compound = rsize.length === 0;\n\n // parses the rtcp-mux attrіbute.\n // Note that Edge does not support unmuxed RTCP.\n var mux = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-mux');\n rtcpParameters.mux = mux.length > 0;\n\n return rtcpParameters;\n};\n\n// parses either a=msid: or a=ssrc:... msid lines and returns\n// the id of the MediaStream and MediaStreamTrack.\nSDPUtils.parseMsid = function(mediaSection) {\n var parts;\n var spec = SDPUtils.matchPrefix(mediaSection, 'a=msid:');\n if (spec.length === 1) {\n parts = spec[0].substr(7).split(' ');\n return {stream: parts[0], track: parts[1]};\n }\n var planB = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')\n .map(function(line) {\n return SDPUtils.parseSsrcMedia(line);\n })\n .filter(function(msidParts) {\n return msidParts.attribute === 'msid';\n });\n if (planB.length > 0) {\n parts = planB[0].value.split(' ');\n return {stream: parts[0], track: parts[1]};\n }\n};\n\n// SCTP\n// parses draft-ietf-mmusic-sctp-sdp-26 first and falls back\n// to draft-ietf-mmusic-sctp-sdp-05\nSDPUtils.parseSctpDescription = function(mediaSection) {\n var mline = SDPUtils.parseMLine(mediaSection);\n var maxSizeLine = SDPUtils.matchPrefix(mediaSection, 'a=max-message-size:');\n var maxMessageSize;\n if (maxSizeLine.length > 0) {\n maxMessageSize = parseInt(maxSizeLine[0].substr(19), 10);\n }\n if (isNaN(maxMessageSize)) {\n maxMessageSize = 65536;\n }\n var sctpPort = SDPUtils.matchPrefix(mediaSection, 'a=sctp-port:');\n if (sctpPort.length > 0) {\n return {\n port: parseInt(sctpPort[0].substr(12), 10),\n protocol: mline.fmt,\n maxMessageSize: maxMessageSize\n };\n }\n var sctpMapLines = SDPUtils.matchPrefix(mediaSection, 'a=sctpmap:');\n if (sctpMapLines.length > 0) {\n var parts = SDPUtils.matchPrefix(mediaSection, 'a=sctpmap:')[0]\n .substr(10)\n .split(' ');\n return {\n port: parseInt(parts[0], 10),\n protocol: parts[1],\n maxMessageSize: maxMessageSize\n };\n }\n};\n\n// SCTP\n// outputs the draft-ietf-mmusic-sctp-sdp-26 version that all browsers\n// support by now receiving in this format, unless we originally parsed\n// as the draft-ietf-mmusic-sctp-sdp-05 format (indicated by the m-line\n// protocol of DTLS/SCTP -- without UDP/ or TCP/)\nSDPUtils.writeSctpDescription = function(media, sctp) {\n var output = [];\n if (media.protocol !== 'DTLS/SCTP') {\n output = [\n 'm=' + media.kind + ' 9 ' + media.protocol + ' ' + sctp.protocol + '\\r\\n',\n 'c=IN IP4 0.0.0.0\\r\\n',\n 'a=sctp-port:' + sctp.port + '\\r\\n'\n ];\n } else {\n output = [\n 'm=' + media.kind + ' 9 ' + media.protocol + ' ' + sctp.port + '\\r\\n',\n 'c=IN IP4 0.0.0.0\\r\\n',\n 'a=sctpmap:' + sctp.port + ' ' + sctp.protocol + ' 65535\\r\\n'\n ];\n }\n if (sctp.maxMessageSize !== undefined) {\n output.push('a=max-message-size:' + sctp.maxMessageSize + '\\r\\n');\n }\n return output.join('');\n};\n\n// Generate a session ID for SDP.\n// https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-20#section-5.2.1\n// recommends using a cryptographically random +ve 64-bit value\n// but right now this should be acceptable and within the right range\nSDPUtils.generateSessionId = function() {\n return Math.random().toString().substr(2, 21);\n};\n\n// Write boilder plate for start of SDP\n// sessId argument is optional - if not supplied it will\n// be generated randomly\n// sessVersion is optional and defaults to 2\n// sessUser is optional and defaults to 'thisisadapterortc'\nSDPUtils.writeSessionBoilerplate = function(sessId, sessVer, sessUser) {\n var sessionId;\n var version = sessVer !== undefined ? sessVer : 2;\n if (sessId) {\n sessionId = sessId;\n } else {\n sessionId = SDPUtils.generateSessionId();\n }\n var user = sessUser || 'thisisadapterortc';\n // FIXME: sess-id should be an NTP timestamp.\n return 'v=0\\r\\n' +\n 'o=' + user + ' ' + sessionId + ' ' + version +\n ' IN IP4 127.0.0.1\\r\\n' +\n 's=-\\r\\n' +\n 't=0 0\\r\\n';\n};\n\nSDPUtils.writeMediaSection = function(transceiver, caps, type, stream) {\n var sdp = SDPUtils.writeRtpDescription(transceiver.kind, caps);\n\n // Map ICE parameters (ufrag, pwd) to SDP.\n sdp += SDPUtils.writeIceParameters(\n transceiver.iceGatherer.getLocalParameters());\n\n // Map DTLS parameters to SDP.\n sdp += SDPUtils.writeDtlsParameters(\n transceiver.dtlsTransport.getLocalParameters(),\n type === 'offer' ? 'actpass' : 'active');\n\n sdp += 'a=mid:' + transceiver.mid + '\\r\\n';\n\n if (transceiver.direction) {\n sdp += 'a=' + transceiver.direction + '\\r\\n';\n } else if (transceiver.rtpSender && transceiver.rtpReceiver) {\n sdp += 'a=sendrecv\\r\\n';\n } else if (transceiver.rtpSender) {\n sdp += 'a=sendonly\\r\\n';\n } else if (transceiver.rtpReceiver) {\n sdp += 'a=recvonly\\r\\n';\n } else {\n sdp += 'a=inactive\\r\\n';\n }\n\n if (transceiver.rtpSender) {\n // spec.\n var msid = 'msid:' + stream.id + ' ' +\n transceiver.rtpSender.track.id + '\\r\\n';\n sdp += 'a=' + msid;\n\n // for Chrome.\n sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc +\n ' ' + msid;\n if (transceiver.sendEncodingParameters[0].rtx) {\n sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc +\n ' ' + msid;\n sdp += 'a=ssrc-group:FID ' +\n transceiver.sendEncodingParameters[0].ssrc + ' ' +\n transceiver.sendEncodingParameters[0].rtx.ssrc +\n '\\r\\n';\n }\n }\n // FIXME: this should be written by writeRtpDescription.\n sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc +\n ' cname:' + SDPUtils.localCName + '\\r\\n';\n if (transceiver.rtpSender && transceiver.sendEncodingParameters[0].rtx) {\n sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc +\n ' cname:' + SDPUtils.localCName + '\\r\\n';\n }\n return sdp;\n};\n\n// Gets the direction from the mediaSection or the sessionpart.\nSDPUtils.getDirection = function(mediaSection, sessionpart) {\n // Look for sendrecv, sendonly, recvonly, inactive, default to sendrecv.\n var lines = SDPUtils.splitLines(mediaSection);\n for (var i = 0; i < lines.length; i++) {\n switch (lines[i]) {\n case 'a=sendrecv':\n case 'a=sendonly':\n case 'a=recvonly':\n case 'a=inactive':\n return lines[i].substr(2);\n default:\n // FIXME: What should happen here?\n }\n }\n if (sessionpart) {\n return SDPUtils.getDirection(sessionpart);\n }\n return 'sendrecv';\n};\n\nSDPUtils.getKind = function(mediaSection) {\n var lines = SDPUtils.splitLines(mediaSection);\n var mline = lines[0].split(' ');\n return mline[0].substr(2);\n};\n\nSDPUtils.isRejected = function(mediaSection) {\n return mediaSection.split(' ', 2)[1] === '0';\n};\n\nSDPUtils.parseMLine = function(mediaSection) {\n var lines = SDPUtils.splitLines(mediaSection);\n var parts = lines[0].substr(2).split(' ');\n return {\n kind: parts[0],\n port: parseInt(parts[1], 10),\n protocol: parts[2],\n fmt: parts.slice(3).join(' ')\n };\n};\n\nSDPUtils.parseOLine = function(mediaSection) {\n var line = SDPUtils.matchPrefix(mediaSection, 'o=')[0];\n var parts = line.substr(2).split(' ');\n return {\n username: parts[0],\n sessionId: parts[1],\n sessionVersion: parseInt(parts[2], 10),\n netType: parts[3],\n addressType: parts[4],\n address: parts[5]\n };\n};\n\n// a very naive interpretation of a valid SDP.\nSDPUtils.isValidSDP = function(blob) {\n if (typeof blob !== 'string' || blob.length === 0) {\n return false;\n }\n var lines = SDPUtils.splitLines(blob);\n for (var i = 0; i < lines.length; i++) {\n if (lines[i].length < 2 || lines[i].charAt(1) !== '=') {\n return false;\n }\n // TODO: check the modifier a bit more.\n }\n return true;\n};\n\n// Expose public methods.\nif (typeof module === 'object') {\n module.exports = SDPUtils;\n}\n","/*\n * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n /* eslint-env node */\n'use strict';\n\nvar SDPUtils = require('sdp');\n\nfunction fixStatsType(stat) {\n return {\n inboundrtp: 'inbound-rtp',\n outboundrtp: 'outbound-rtp',\n candidatepair: 'candidate-pair',\n localcandidate: 'local-candidate',\n remotecandidate: 'remote-candidate'\n }[stat.type] || stat.type;\n}\n\nfunction writeMediaSection(transceiver, caps, type, stream, dtlsRole) {\n var sdp = SDPUtils.writeRtpDescription(transceiver.kind, caps);\n\n // Map ICE parameters (ufrag, pwd) to SDP.\n sdp += SDPUtils.writeIceParameters(\n transceiver.iceGatherer.getLocalParameters());\n\n // Map DTLS parameters to SDP.\n sdp += SDPUtils.writeDtlsParameters(\n transceiver.dtlsTransport.getLocalParameters(),\n type === 'offer' ? 'actpass' : dtlsRole || 'active');\n\n sdp += 'a=mid:' + transceiver.mid + '\\r\\n';\n\n if (transceiver.rtpSender && transceiver.rtpReceiver) {\n sdp += 'a=sendrecv\\r\\n';\n } else if (transceiver.rtpSender) {\n sdp += 'a=sendonly\\r\\n';\n } else if (transceiver.rtpReceiver) {\n sdp += 'a=recvonly\\r\\n';\n } else {\n sdp += 'a=inactive\\r\\n';\n }\n\n if (transceiver.rtpSender) {\n var trackId = transceiver.rtpSender._initialTrackId ||\n transceiver.rtpSender.track.id;\n transceiver.rtpSender._initialTrackId = trackId;\n // spec.\n var msid = 'msid:' + (stream ? stream.id : '-') + ' ' +\n trackId + '\\r\\n';\n sdp += 'a=' + msid;\n // for Chrome. Legacy should no longer be required.\n sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc +\n ' ' + msid;\n\n // RTX\n if (transceiver.sendEncodingParameters[0].rtx) {\n sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc +\n ' ' + msid;\n sdp += 'a=ssrc-group:FID ' +\n transceiver.sendEncodingParameters[0].ssrc + ' ' +\n transceiver.sendEncodingParameters[0].rtx.ssrc +\n '\\r\\n';\n }\n }\n // FIXME: this should be written by writeRtpDescription.\n sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc +\n ' cname:' + SDPUtils.localCName + '\\r\\n';\n if (transceiver.rtpSender && transceiver.sendEncodingParameters[0].rtx) {\n sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc +\n ' cname:' + SDPUtils.localCName + '\\r\\n';\n }\n return sdp;\n}\n\n// Edge does not like\n// 1) stun: filtered after 14393 unless ?transport=udp is present\n// 2) turn: that does not have all of turn:host:port?transport=udp\n// 3) turn: with ipv6 addresses\n// 4) turn: occurring muliple times\nfunction filterIceServers(iceServers, edgeVersion) {\n var hasTurn = false;\n iceServers = JSON.parse(JSON.stringify(iceServers));\n return iceServers.filter(function(server) {\n if (server && (server.urls || server.url)) {\n var urls = server.urls || server.url;\n if (server.url && !server.urls) {\n console.warn('RTCIceServer.url is deprecated! Use urls instead.');\n }\n var isString = typeof urls === 'string';\n if (isString) {\n urls = [urls];\n }\n urls = urls.filter(function(url) {\n var validTurn = url.indexOf('turn:') === 0 &&\n url.indexOf('transport=udp') !== -1 &&\n url.indexOf('turn:[') === -1 &&\n !hasTurn;\n\n if (validTurn) {\n hasTurn = true;\n return true;\n }\n return url.indexOf('stun:') === 0 && edgeVersion >= 14393 &&\n url.indexOf('?transport=udp') === -1;\n });\n\n delete server.url;\n server.urls = isString ? urls[0] : urls;\n return !!urls.length;\n }\n });\n}\n\n// Determines the intersection of local and remote capabilities.\nfunction getCommonCapabilities(localCapabilities, remoteCapabilities) {\n var commonCapabilities = {\n codecs: [],\n headerExtensions: [],\n fecMechanisms: []\n };\n\n var findCodecByPayloadType = function(pt, codecs) {\n pt = parseInt(pt, 10);\n for (var i = 0; i < codecs.length; i++) {\n if (codecs[i].payloadType === pt ||\n codecs[i].preferredPayloadType === pt) {\n return codecs[i];\n }\n }\n };\n\n var rtxCapabilityMatches = function(lRtx, rRtx, lCodecs, rCodecs) {\n var lCodec = findCodecByPayloadType(lRtx.parameters.apt, lCodecs);\n var rCodec = findCodecByPayloadType(rRtx.parameters.apt, rCodecs);\n return lCodec && rCodec &&\n lCodec.name.toLowerCase() === rCodec.name.toLowerCase();\n };\n\n localCapabilities.codecs.forEach(function(lCodec) {\n for (var i = 0; i < remoteCapabilities.codecs.length; i++) {\n var rCodec = remoteCapabilities.codecs[i];\n if (lCodec.name.toLowerCase() === rCodec.name.toLowerCase() &&\n lCodec.clockRate === rCodec.clockRate) {\n if (lCodec.name.toLowerCase() === 'rtx' &&\n lCodec.parameters && rCodec.parameters.apt) {\n // for RTX we need to find the local rtx that has a apt\n // which points to the same local codec as the remote one.\n if (!rtxCapabilityMatches(lCodec, rCodec,\n localCapabilities.codecs, remoteCapabilities.codecs)) {\n continue;\n }\n }\n rCodec = JSON.parse(JSON.stringify(rCodec)); // deepcopy\n // number of channels is the highest common number of channels\n rCodec.numChannels = Math.min(lCodec.numChannels,\n rCodec.numChannels);\n // push rCodec so we reply with offerer payload type\n commonCapabilities.codecs.push(rCodec);\n\n // determine common feedback mechanisms\n rCodec.rtcpFeedback = rCodec.rtcpFeedback.filter(function(fb) {\n for (var j = 0; j < lCodec.rtcpFeedback.length; j++) {\n if (lCodec.rtcpFeedback[j].type === fb.type &&\n lCodec.rtcpFeedback[j].parameter === fb.parameter) {\n return true;\n }\n }\n return false;\n });\n // FIXME: also need to determine .parameters\n // see https://github.com/openpeer/ortc/issues/569\n break;\n }\n }\n });\n\n localCapabilities.headerExtensions.forEach(function(lHeaderExtension) {\n for (var i = 0; i < remoteCapabilities.headerExtensions.length;\n i++) {\n var rHeaderExtension = remoteCapabilities.headerExtensions[i];\n if (lHeaderExtension.uri === rHeaderExtension.uri) {\n commonCapabilities.headerExtensions.push(rHeaderExtension);\n break;\n }\n }\n });\n\n // FIXME: fecMechanisms\n return commonCapabilities;\n}\n\n// is action=setLocalDescription with type allowed in signalingState\nfunction isActionAllowedInSignalingState(action, type, signalingState) {\n return {\n offer: {\n setLocalDescription: ['stable', 'have-local-offer'],\n setRemoteDescription: ['stable', 'have-remote-offer']\n },\n answer: {\n setLocalDescription: ['have-remote-offer', 'have-local-pranswer'],\n setRemoteDescription: ['have-local-offer', 'have-remote-pranswer']\n }\n }[type][action].indexOf(signalingState) !== -1;\n}\n\nfunction maybeAddCandidate(iceTransport, candidate) {\n // Edge's internal representation adds some fields therefore\n // not all fieldѕ are taken into account.\n var alreadyAdded = iceTransport.getRemoteCandidates()\n .find(function(remoteCandidate) {\n return candidate.foundation === remoteCandidate.foundation &&\n candidate.ip === remoteCandidate.ip &&\n candidate.port === remoteCandidate.port &&\n candidate.priority === remoteCandidate.priority &&\n candidate.protocol === remoteCandidate.protocol &&\n candidate.type === remoteCandidate.type;\n });\n if (!alreadyAdded) {\n iceTransport.addRemoteCandidate(candidate);\n }\n return !alreadyAdded;\n}\n\n\nfunction makeError(name, description) {\n var e = new Error(description);\n e.name = name;\n // legacy error codes from https://heycam.github.io/webidl/#idl-DOMException-error-names\n e.code = {\n NotSupportedError: 9,\n InvalidStateError: 11,\n InvalidAccessError: 15,\n TypeError: undefined,\n OperationError: undefined\n }[name];\n return e;\n}\n\nmodule.exports = function(window, edgeVersion) {\n // https://w3c.github.io/mediacapture-main/#mediastream\n // Helper function to add the track to the stream and\n // dispatch the event ourselves.\n function addTrackToStreamAndFireEvent(track, stream) {\n stream.addTrack(track);\n stream.dispatchEvent(new window.MediaStreamTrackEvent('addtrack',\n {track: track}));\n }\n\n function removeTrackFromStreamAndFireEvent(track, stream) {\n stream.removeTrack(track);\n stream.dispatchEvent(new window.MediaStreamTrackEvent('removetrack',\n {track: track}));\n }\n\n function fireAddTrack(pc, track, receiver, streams) {\n var trackEvent = new Event('track');\n trackEvent.track = track;\n trackEvent.receiver = receiver;\n trackEvent.transceiver = {receiver: receiver};\n trackEvent.streams = streams;\n window.setTimeout(function() {\n pc._dispatchEvent('track', trackEvent);\n });\n }\n\n var RTCPeerConnection = function(config) {\n var pc = this;\n\n var _eventTarget = document.createDocumentFragment();\n ['addEventListener', 'removeEventListener', 'dispatchEvent']\n .forEach(function(method) {\n pc[method] = _eventTarget[method].bind(_eventTarget);\n });\n\n this.canTrickleIceCandidates = null;\n\n this.needNegotiation = false;\n\n this.localStreams = [];\n this.remoteStreams = [];\n\n this._localDescription = null;\n this._remoteDescription = null;\n\n this.signalingState = 'stable';\n this.iceConnectionState = 'new';\n this.connectionState = 'new';\n this.iceGatheringState = 'new';\n\n config = JSON.parse(JSON.stringify(config || {}));\n\n this.usingBundle = config.bundlePolicy === 'max-bundle';\n if (config.rtcpMuxPolicy === 'negotiate') {\n throw(makeError('NotSupportedError',\n 'rtcpMuxPolicy \\'negotiate\\' is not supported'));\n } else if (!config.rtcpMuxPolicy) {\n config.rtcpMuxPolicy = 'require';\n }\n\n switch (config.iceTransportPolicy) {\n case 'all':\n case 'relay':\n break;\n default:\n config.iceTransportPolicy = 'all';\n break;\n }\n\n switch (config.bundlePolicy) {\n case 'balanced':\n case 'max-compat':\n case 'max-bundle':\n break;\n default:\n config.bundlePolicy = 'balanced';\n break;\n }\n\n config.iceServers = filterIceServers(config.iceServers || [], edgeVersion);\n\n this._iceGatherers = [];\n if (config.iceCandidatePoolSize) {\n for (var i = config.iceCandidatePoolSize; i > 0; i--) {\n this._iceGatherers.push(new window.RTCIceGatherer({\n iceServers: config.iceServers,\n gatherPolicy: config.iceTransportPolicy\n }));\n }\n } else {\n config.iceCandidatePoolSize = 0;\n }\n\n this._config = config;\n\n // per-track iceGathers, iceTransports, dtlsTransports, rtpSenders, ...\n // everything that is needed to describe a SDP m-line.\n this.transceivers = [];\n\n this._sdpSessionId = SDPUtils.generateSessionId();\n this._sdpSessionVersion = 0;\n\n this._dtlsRole = undefined; // role for a=setup to use in answers.\n\n this._isClosed = false;\n };\n\n Object.defineProperty(RTCPeerConnection.prototype, 'localDescription', {\n configurable: true,\n get: function() {\n return this._localDescription;\n }\n });\n Object.defineProperty(RTCPeerConnection.prototype, 'remoteDescription', {\n configurable: true,\n get: function() {\n return this._remoteDescription;\n }\n });\n\n // set up event handlers on prototype\n RTCPeerConnection.prototype.onicecandidate = null;\n RTCPeerConnection.prototype.onaddstream = null;\n RTCPeerConnection.prototype.ontrack = null;\n RTCPeerConnection.prototype.onremovestream = null;\n RTCPeerConnection.prototype.onsignalingstatechange = null;\n RTCPeerConnection.prototype.oniceconnectionstatechange = null;\n RTCPeerConnection.prototype.onconnectionstatechange = null;\n RTCPeerConnection.prototype.onicegatheringstatechange = null;\n RTCPeerConnection.prototype.onnegotiationneeded = null;\n RTCPeerConnection.prototype.ondatachannel = null;\n\n RTCPeerConnection.prototype._dispatchEvent = function(name, event) {\n if (this._isClosed) {\n return;\n }\n this.dispatchEvent(event);\n if (typeof this['on' + name] === 'function') {\n this['on' + name](event);\n }\n };\n\n RTCPeerConnection.prototype._emitGatheringStateChange = function() {\n var event = new Event('icegatheringstatechange');\n this._dispatchEvent('icegatheringstatechange', event);\n };\n\n RTCPeerConnection.prototype.getConfiguration = function() {\n return this._config;\n };\n\n RTCPeerConnection.prototype.getLocalStreams = function() {\n return this.localStreams;\n };\n\n RTCPeerConnection.prototype.getRemoteStreams = function() {\n return this.remoteStreams;\n };\n\n // internal helper to create a transceiver object.\n // (which is not yet the same as the WebRTC 1.0 transceiver)\n RTCPeerConnection.prototype._createTransceiver = function(kind, doNotAdd) {\n var hasBundleTransport = this.transceivers.length > 0;\n var transceiver = {\n track: null,\n iceGatherer: null,\n iceTransport: null,\n dtlsTransport: null,\n localCapabilities: null,\n remoteCapabilities: null,\n rtpSender: null,\n rtpReceiver: null,\n kind: kind,\n mid: null,\n sendEncodingParameters: null,\n recvEncodingParameters: null,\n stream: null,\n associatedRemoteMediaStreams: [],\n wantReceive: true\n };\n if (this.usingBundle && hasBundleTransport) {\n transceiver.iceTransport = this.transceivers[0].iceTransport;\n transceiver.dtlsTransport = this.transceivers[0].dtlsTransport;\n } else {\n var transports = this._createIceAndDtlsTransports();\n transceiver.iceTransport = transports.iceTransport;\n transceiver.dtlsTransport = transports.dtlsTransport;\n }\n if (!doNotAdd) {\n this.transceivers.push(transceiver);\n }\n return transceiver;\n };\n\n RTCPeerConnection.prototype.addTrack = function(track, stream) {\n if (this._isClosed) {\n throw makeError('InvalidStateError',\n 'Attempted to call addTrack on a closed peerconnection.');\n }\n\n var alreadyExists = this.transceivers.find(function(s) {\n return s.track === track;\n });\n\n if (alreadyExists) {\n throw makeError('InvalidAccessError', 'Track already exists.');\n }\n\n var transceiver;\n for (var i = 0; i < this.transceivers.length; i++) {\n if (!this.transceivers[i].track &&\n this.transceivers[i].kind === track.kind) {\n transceiver = this.transceivers[i];\n }\n }\n if (!transceiver) {\n transceiver = this._createTransceiver(track.kind);\n }\n\n this._maybeFireNegotiationNeeded();\n\n if (this.localStreams.indexOf(stream) === -1) {\n this.localStreams.push(stream);\n }\n\n transceiver.track = track;\n transceiver.stream = stream;\n transceiver.rtpSender = new window.RTCRtpSender(track,\n transceiver.dtlsTransport);\n return transceiver.rtpSender;\n };\n\n RTCPeerConnection.prototype.addStream = function(stream) {\n var pc = this;\n if (edgeVersion >= 15025) {\n stream.getTracks().forEach(function(track) {\n pc.addTrack(track, stream);\n });\n } else {\n // Clone is necessary for local demos mostly, attaching directly\n // to two different senders does not work (build 10547).\n // Fixed in 15025 (or earlier)\n var clonedStream = stream.clone();\n stream.getTracks().forEach(function(track, idx) {\n var clonedTrack = clonedStream.getTracks()[idx];\n track.addEventListener('enabled', function(event) {\n clonedTrack.enabled = event.enabled;\n });\n });\n clonedStream.getTracks().forEach(function(track) {\n pc.addTrack(track, clonedStream);\n });\n }\n };\n\n RTCPeerConnection.prototype.removeTrack = function(sender) {\n if (this._isClosed) {\n throw makeError('InvalidStateError',\n 'Attempted to call removeTrack on a closed peerconnection.');\n }\n\n if (!(sender instanceof window.RTCRtpSender)) {\n throw new TypeError('Argument 1 of RTCPeerConnection.removeTrack ' +\n 'does not implement interface RTCRtpSender.');\n }\n\n var transceiver = this.transceivers.find(function(t) {\n return t.rtpSender === sender;\n });\n\n if (!transceiver) {\n throw makeError('InvalidAccessError',\n 'Sender was not created by this connection.');\n }\n var stream = transceiver.stream;\n\n transceiver.rtpSender.stop();\n transceiver.rtpSender = null;\n transceiver.track = null;\n transceiver.stream = null;\n\n // remove the stream from the set of local streams\n var localStreams = this.transceivers.map(function(t) {\n return t.stream;\n });\n if (localStreams.indexOf(stream) === -1 &&\n this.localStreams.indexOf(stream) > -1) {\n this.localStreams.splice(this.localStreams.indexOf(stream), 1);\n }\n\n this._maybeFireNegotiationNeeded();\n };\n\n RTCPeerConnection.prototype.removeStream = function(stream) {\n var pc = this;\n stream.getTracks().forEach(function(track) {\n var sender = pc.getSenders().find(function(s) {\n return s.track === track;\n });\n if (sender) {\n pc.removeTrack(sender);\n }\n });\n };\n\n RTCPeerConnection.prototype.getSenders = function() {\n return this.transceivers.filter(function(transceiver) {\n return !!transceiver.rtpSender;\n })\n .map(function(transceiver) {\n return transceiver.rtpSender;\n });\n };\n\n RTCPeerConnection.prototype.getReceivers = function() {\n return this.transceivers.filter(function(transceiver) {\n return !!transceiver.rtpReceiver;\n })\n .map(function(transceiver) {\n return transceiver.rtpReceiver;\n });\n };\n\n\n RTCPeerConnection.prototype._createIceGatherer = function(sdpMLineIndex,\n usingBundle) {\n var pc = this;\n if (usingBundle && sdpMLineIndex > 0) {\n return this.transceivers[0].iceGatherer;\n } else if (this._iceGatherers.length) {\n return this._iceGatherers.shift();\n }\n var iceGatherer = new window.RTCIceGatherer({\n iceServers: this._config.iceServers,\n gatherPolicy: this._config.iceTransportPolicy\n });\n Object.defineProperty(iceGatherer, 'state',\n {value: 'new', writable: true}\n );\n\n this.transceivers[sdpMLineIndex].bufferedCandidateEvents = [];\n this.transceivers[sdpMLineIndex].bufferCandidates = function(event) {\n var end = !event.candidate || Object.keys(event.candidate).length === 0;\n // polyfill since RTCIceGatherer.state is not implemented in\n // Edge 10547 yet.\n iceGatherer.state = end ? 'completed' : 'gathering';\n if (pc.transceivers[sdpMLineIndex].bufferedCandidateEvents !== null) {\n pc.transceivers[sdpMLineIndex].bufferedCandidateEvents.push(event);\n }\n };\n iceGatherer.addEventListener('localcandidate',\n this.transceivers[sdpMLineIndex].bufferCandidates);\n return iceGatherer;\n };\n\n // start gathering from an RTCIceGatherer.\n RTCPeerConnection.prototype._gather = function(mid, sdpMLineIndex) {\n var pc = this;\n var iceGatherer = this.transceivers[sdpMLineIndex].iceGatherer;\n if (iceGatherer.onlocalcandidate) {\n return;\n }\n var bufferedCandidateEvents =\n this.transceivers[sdpMLineIndex].bufferedCandidateEvents;\n this.transceivers[sdpMLineIndex].bufferedCandidateEvents = null;\n iceGatherer.removeEventListener('localcandidate',\n this.transceivers[sdpMLineIndex].bufferCandidates);\n iceGatherer.onlocalcandidate = function(evt) {\n if (pc.usingBundle && sdpMLineIndex > 0) {\n // if we know that we use bundle we can drop candidates with\n // ѕdpMLineIndex > 0. If we don't do this then our state gets\n // confused since we dispose the extra ice gatherer.\n return;\n }\n var event = new Event('icecandidate');\n event.candidate = {sdpMid: mid, sdpMLineIndex: sdpMLineIndex};\n\n var cand = evt.candidate;\n // Edge emits an empty object for RTCIceCandidateComplete‥\n var end = !cand || Object.keys(cand).length === 0;\n if (end) {\n // polyfill since RTCIceGatherer.state is not implemented in\n // Edge 10547 yet.\n if (iceGatherer.state === 'new' || iceGatherer.state === 'gathering') {\n iceGatherer.state = 'completed';\n }\n } else {\n if (iceGatherer.state === 'new') {\n iceGatherer.state = 'gathering';\n }\n // RTCIceCandidate doesn't have a component, needs to be added\n cand.component = 1;\n // also the usernameFragment. TODO: update SDP to take both variants.\n cand.ufrag = iceGatherer.getLocalParameters().usernameFragment;\n\n var serializedCandidate = SDPUtils.writeCandidate(cand);\n event.candidate = Object.assign(event.candidate,\n SDPUtils.parseCandidate(serializedCandidate));\n\n event.candidate.candidate = serializedCandidate;\n event.candidate.toJSON = function() {\n return {\n candidate: event.candidate.candidate,\n sdpMid: event.candidate.sdpMid,\n sdpMLineIndex: event.candidate.sdpMLineIndex,\n usernameFragment: event.candidate.usernameFragment\n };\n };\n }\n\n // update local description.\n var sections = SDPUtils.getMediaSections(pc._localDescription.sdp);\n if (!end) {\n sections[event.candidate.sdpMLineIndex] +=\n 'a=' + event.candidate.candidate + '\\r\\n';\n } else {\n sections[event.candidate.sdpMLineIndex] +=\n 'a=end-of-candidates\\r\\n';\n }\n pc._localDescription.sdp =\n SDPUtils.getDescription(pc._localDescription.sdp) +\n sections.join('');\n var complete = pc.transceivers.every(function(transceiver) {\n return transceiver.iceGatherer &&\n transceiver.iceGatherer.state === 'completed';\n });\n\n if (pc.iceGatheringState !== 'gathering') {\n pc.iceGatheringState = 'gathering';\n pc._emitGatheringStateChange();\n }\n\n // Emit candidate. Also emit null candidate when all gatherers are\n // complete.\n if (!end) {\n pc._dispatchEvent('icecandidate', event);\n }\n if (complete) {\n pc._dispatchEvent('icecandidate', new Event('icecandidate'));\n pc.iceGatheringState = 'complete';\n pc._emitGatheringStateChange();\n }\n };\n\n // emit already gathered candidates.\n window.setTimeout(function() {\n bufferedCandidateEvents.forEach(function(e) {\n iceGatherer.onlocalcandidate(e);\n });\n }, 0);\n };\n\n // Create ICE transport and DTLS transport.\n RTCPeerConnection.prototype._createIceAndDtlsTransports = function() {\n var pc = this;\n var iceTransport = new window.RTCIceTransport(null);\n iceTransport.onicestatechange = function() {\n pc._updateIceConnectionState();\n pc._updateConnectionState();\n };\n\n var dtlsTransport = new window.RTCDtlsTransport(iceTransport);\n dtlsTransport.ondtlsstatechange = function() {\n pc._updateConnectionState();\n };\n dtlsTransport.onerror = function() {\n // onerror does not set state to failed by itself.\n Object.defineProperty(dtlsTransport, 'state',\n {value: 'failed', writable: true});\n pc._updateConnectionState();\n };\n\n return {\n iceTransport: iceTransport,\n dtlsTransport: dtlsTransport\n };\n };\n\n // Destroy ICE gatherer, ICE transport and DTLS transport.\n // Without triggering the callbacks.\n RTCPeerConnection.prototype._disposeIceAndDtlsTransports = function(\n sdpMLineIndex) {\n var iceGatherer = this.transceivers[sdpMLineIndex].iceGatherer;\n if (iceGatherer) {\n delete iceGatherer.onlocalcandidate;\n delete this.transceivers[sdpMLineIndex].iceGatherer;\n }\n var iceTransport = this.transceivers[sdpMLineIndex].iceTransport;\n if (iceTransport) {\n delete iceTransport.onicestatechange;\n delete this.transceivers[sdpMLineIndex].iceTransport;\n }\n var dtlsTransport = this.transceivers[sdpMLineIndex].dtlsTransport;\n if (dtlsTransport) {\n delete dtlsTransport.ondtlsstatechange;\n delete dtlsTransport.onerror;\n delete this.transceivers[sdpMLineIndex].dtlsTransport;\n }\n };\n\n // Start the RTP Sender and Receiver for a transceiver.\n RTCPeerConnection.prototype._transceive = function(transceiver,\n send, recv) {\n var params = getCommonCapabilities(transceiver.localCapabilities,\n transceiver.remoteCapabilities);\n if (send && transceiver.rtpSender) {\n params.encodings = transceiver.sendEncodingParameters;\n params.rtcp = {\n cname: SDPUtils.localCName,\n compound: transceiver.rtcpParameters.compound\n };\n if (transceiver.recvEncodingParameters.length) {\n params.rtcp.ssrc = transceiver.recvEncodingParameters[0].ssrc;\n }\n transceiver.rtpSender.send(params);\n }\n if (recv && transceiver.rtpReceiver && params.codecs.length > 0) {\n // remove RTX field in Edge 14942\n if (transceiver.kind === 'video'\n && transceiver.recvEncodingParameters\n && edgeVersion < 15019) {\n transceiver.recvEncodingParameters.forEach(function(p) {\n delete p.rtx;\n });\n }\n if (transceiver.recvEncodingParameters.length) {\n params.encodings = transceiver.recvEncodingParameters;\n } else {\n params.encodings = [{}];\n }\n params.rtcp = {\n compound: transceiver.rtcpParameters.compound\n };\n if (transceiver.rtcpParameters.cname) {\n params.rtcp.cname = transceiver.rtcpParameters.cname;\n }\n if (transceiver.sendEncodingParameters.length) {\n params.rtcp.ssrc = transceiver.sendEncodingParameters[0].ssrc;\n }\n transceiver.rtpReceiver.receive(params);\n }\n };\n\n RTCPeerConnection.prototype.setLocalDescription = function(description) {\n var pc = this;\n\n // Note: pranswer is not supported.\n if (['offer', 'answer'].indexOf(description.type) === -1) {\n return Promise.reject(makeError('TypeError',\n 'Unsupported type \"' + description.type + '\"'));\n }\n\n if (!isActionAllowedInSignalingState('setLocalDescription',\n description.type, pc.signalingState) || pc._isClosed) {\n return Promise.reject(makeError('InvalidStateError',\n 'Can not set local ' + description.type +\n ' in state ' + pc.signalingState));\n }\n\n var sections;\n var sessionpart;\n if (description.type === 'offer') {\n // VERY limited support for SDP munging. Limited to:\n // * changing the order of codecs\n sections = SDPUtils.splitSections(description.sdp);\n sessionpart = sections.shift();\n sections.forEach(function(mediaSection, sdpMLineIndex) {\n var caps = SDPUtils.parseRtpParameters(mediaSection);\n pc.transceivers[sdpMLineIndex].localCapabilities = caps;\n });\n\n pc.transceivers.forEach(function(transceiver, sdpMLineIndex) {\n pc._gather(transceiver.mid, sdpMLineIndex);\n });\n } else if (description.type === 'answer') {\n sections = SDPUtils.splitSections(pc._remoteDescription.sdp);\n sessionpart = sections.shift();\n var isIceLite = SDPUtils.matchPrefix(sessionpart,\n 'a=ice-lite').length > 0;\n sections.forEach(function(mediaSection, sdpMLineIndex) {\n var transceiver = pc.transceivers[sdpMLineIndex];\n var iceGatherer = transceiver.iceGatherer;\n var iceTransport = transceiver.iceTransport;\n var dtlsTransport = transceiver.dtlsTransport;\n var localCapabilities = transceiver.localCapabilities;\n var remoteCapabilities = transceiver.remoteCapabilities;\n\n // treat bundle-only as not-rejected.\n var rejected = SDPUtils.isRejected(mediaSection) &&\n SDPUtils.matchPrefix(mediaSection, 'a=bundle-only').length === 0;\n\n if (!rejected && !transceiver.rejected) {\n var remoteIceParameters = SDPUtils.getIceParameters(\n mediaSection, sessionpart);\n var remoteDtlsParameters = SDPUtils.getDtlsParameters(\n mediaSection, sessionpart);\n if (isIceLite) {\n remoteDtlsParameters.role = 'server';\n }\n\n if (!pc.usingBundle || sdpMLineIndex === 0) {\n pc._gather(transceiver.mid, sdpMLineIndex);\n if (iceTransport.state === 'new') {\n iceTransport.start(iceGatherer, remoteIceParameters,\n isIceLite ? 'controlling' : 'controlled');\n }\n if (dtlsTransport.state === 'new') {\n dtlsTransport.start(remoteDtlsParameters);\n }\n }\n\n // Calculate intersection of capabilities.\n var params = getCommonCapabilities(localCapabilities,\n remoteCapabilities);\n\n // Start the RTCRtpSender. The RTCRtpReceiver for this\n // transceiver has already been started in setRemoteDescription.\n pc._transceive(transceiver,\n params.codecs.length > 0,\n false);\n }\n });\n }\n\n pc._localDescription = {\n type: description.type,\n sdp: description.sdp\n };\n if (description.type === 'offer') {\n pc._updateSignalingState('have-local-offer');\n } else {\n pc._updateSignalingState('stable');\n }\n\n return Promise.resolve();\n };\n\n RTCPeerConnection.prototype.setRemoteDescription = function(description) {\n var pc = this;\n\n // Note: pranswer is not supported.\n if (['offer', 'answer'].indexOf(description.type) === -1) {\n return Promise.reject(makeError('TypeError',\n 'Unsupported type \"' + description.type + '\"'));\n }\n\n if (!isActionAllowedInSignalingState('setRemoteDescription',\n description.type, pc.signalingState) || pc._isClosed) {\n return Promise.reject(makeError('InvalidStateError',\n 'Can not set remote ' + description.type +\n ' in state ' + pc.signalingState));\n }\n\n var streams = {};\n pc.remoteStreams.forEach(function(stream) {\n streams[stream.id] = stream;\n });\n var receiverList = [];\n var sections = SDPUtils.splitSections(description.sdp);\n var sessionpart = sections.shift();\n var isIceLite = SDPUtils.matchPrefix(sessionpart,\n 'a=ice-lite').length > 0;\n var usingBundle = SDPUtils.matchPrefix(sessionpart,\n 'a=group:BUNDLE ').length > 0;\n pc.usingBundle = usingBundle;\n var iceOptions = SDPUtils.matchPrefix(sessionpart,\n 'a=ice-options:')[0];\n if (iceOptions) {\n pc.canTrickleIceCandidates = iceOptions.substr(14).split(' ')\n .indexOf('trickle') >= 0;\n } else {\n pc.canTrickleIceCandidates = false;\n }\n\n sections.forEach(function(mediaSection, sdpMLineIndex) {\n var lines = SDPUtils.splitLines(mediaSection);\n var kind = SDPUtils.getKind(mediaSection);\n // treat bundle-only as not-rejected.\n var rejected = SDPUtils.isRejected(mediaSection) &&\n SDPUtils.matchPrefix(mediaSection, 'a=bundle-only').length === 0;\n var protocol = lines[0].substr(2).split(' ')[2];\n\n var direction = SDPUtils.getDirection(mediaSection, sessionpart);\n var remoteMsid = SDPUtils.parseMsid(mediaSection);\n\n var mid = SDPUtils.getMid(mediaSection) || SDPUtils.generateIdentifier();\n\n // Reject datachannels which are not implemented yet.\n if (rejected || (kind === 'application' && (protocol === 'DTLS/SCTP' ||\n protocol === 'UDP/DTLS/SCTP'))) {\n // TODO: this is dangerous in the case where a non-rejected m-line\n // becomes rejected.\n pc.transceivers[sdpMLineIndex] = {\n mid: mid,\n kind: kind,\n protocol: protocol,\n rejected: true\n };\n return;\n }\n\n if (!rejected && pc.transceivers[sdpMLineIndex] &&\n pc.transceivers[sdpMLineIndex].rejected) {\n // recycle a rejected transceiver.\n pc.transceivers[sdpMLineIndex] = pc._createTransceiver(kind, true);\n }\n\n var transceiver;\n var iceGatherer;\n var iceTransport;\n var dtlsTransport;\n var rtpReceiver;\n var sendEncodingParameters;\n var recvEncodingParameters;\n var localCapabilities;\n\n var track;\n // FIXME: ensure the mediaSection has rtcp-mux set.\n var remoteCapabilities = SDPUtils.parseRtpParameters(mediaSection);\n var remoteIceParameters;\n var remoteDtlsParameters;\n if (!rejected) {\n remoteIceParameters = SDPUtils.getIceParameters(mediaSection,\n sessionpart);\n remoteDtlsParameters = SDPUtils.getDtlsParameters(mediaSection,\n sessionpart);\n remoteDtlsParameters.role = 'client';\n }\n recvEncodingParameters =\n SDPUtils.parseRtpEncodingParameters(mediaSection);\n\n var rtcpParameters = SDPUtils.parseRtcpParameters(mediaSection);\n\n var isComplete = SDPUtils.matchPrefix(mediaSection,\n 'a=end-of-candidates', sessionpart).length > 0;\n var cands = SDPUtils.matchPrefix(mediaSection, 'a=candidate:')\n .map(function(cand) {\n return SDPUtils.parseCandidate(cand);\n })\n .filter(function(cand) {\n return cand.component === 1;\n });\n\n // Check if we can use BUNDLE and dispose transports.\n if ((description.type === 'offer' || description.type === 'answer') &&\n !rejected && usingBundle && sdpMLineIndex > 0 &&\n pc.transceivers[sdpMLineIndex]) {\n pc._disposeIceAndDtlsTransports(sdpMLineIndex);\n pc.transceivers[sdpMLineIndex].iceGatherer =\n pc.transceivers[0].iceGatherer;\n pc.transceivers[sdpMLineIndex].iceTransport =\n pc.transceivers[0].iceTransport;\n pc.transceivers[sdpMLineIndex].dtlsTransport =\n pc.transceivers[0].dtlsTransport;\n if (pc.transceivers[sdpMLineIndex].rtpSender) {\n pc.transceivers[sdpMLineIndex].rtpSender.setTransport(\n pc.transceivers[0].dtlsTransport);\n }\n if (pc.transceivers[sdpMLineIndex].rtpReceiver) {\n pc.transceivers[sdpMLineIndex].rtpReceiver.setTransport(\n pc.transceivers[0].dtlsTransport);\n }\n }\n if (description.type === 'offer' && !rejected) {\n transceiver = pc.transceivers[sdpMLineIndex] ||\n pc._createTransceiver(kind);\n transceiver.mid = mid;\n\n if (!transceiver.iceGatherer) {\n transceiver.iceGatherer = pc._createIceGatherer(sdpMLineIndex,\n usingBundle);\n }\n\n if (cands.length && transceiver.iceTransport.state === 'new') {\n if (isComplete && (!usingBundle || sdpMLineIndex === 0)) {\n transceiver.iceTransport.setRemoteCandidates(cands);\n } else {\n cands.forEach(function(candidate) {\n maybeAddCandidate(transceiver.iceTransport, candidate);\n });\n }\n }\n\n localCapabilities = window.RTCRtpReceiver.getCapabilities(kind);\n\n // filter RTX until additional stuff needed for RTX is implemented\n // in adapter.js\n if (edgeVersion < 15019) {\n localCapabilities.codecs = localCapabilities.codecs.filter(\n function(codec) {\n return codec.name !== 'rtx';\n });\n }\n\n sendEncodingParameters = transceiver.sendEncodingParameters || [{\n ssrc: (2 * sdpMLineIndex + 2) * 1001\n }];\n\n // TODO: rewrite to use http://w3c.github.io/webrtc-pc/#set-associated-remote-streams\n var isNewTrack = false;\n if (direction === 'sendrecv' || direction === 'sendonly') {\n isNewTrack = !transceiver.rtpReceiver;\n rtpReceiver = transceiver.rtpReceiver ||\n new window.RTCRtpReceiver(transceiver.dtlsTransport, kind);\n\n if (isNewTrack) {\n var stream;\n track = rtpReceiver.track;\n // FIXME: does not work with Plan B.\n if (remoteMsid && remoteMsid.stream === '-') {\n // no-op. a stream id of '-' means: no associated stream.\n } else if (remoteMsid) {\n if (!streams[remoteMsid.stream]) {\n streams[remoteMsid.stream] = new window.MediaStream();\n Object.defineProperty(streams[remoteMsid.stream], 'id', {\n get: function() {\n return remoteMsid.stream;\n }\n });\n }\n Object.defineProperty(track, 'id', {\n get: function() {\n return remoteMsid.track;\n }\n });\n stream = streams[remoteMsid.stream];\n } else {\n if (!streams.default) {\n streams.default = new window.MediaStream();\n }\n stream = streams.default;\n }\n if (stream) {\n addTrackToStreamAndFireEvent(track, stream);\n transceiver.associatedRemoteMediaStreams.push(stream);\n }\n receiverList.push([track, rtpReceiver, stream]);\n }\n } else if (transceiver.rtpReceiver && transceiver.rtpReceiver.track) {\n transceiver.associatedRemoteMediaStreams.forEach(function(s) {\n var nativeTrack = s.getTracks().find(function(t) {\n return t.id === transceiver.rtpReceiver.track.id;\n });\n if (nativeTrack) {\n removeTrackFromStreamAndFireEvent(nativeTrack, s);\n }\n });\n transceiver.associatedRemoteMediaStreams = [];\n }\n\n transceiver.localCapabilities = localCapabilities;\n transceiver.remoteCapabilities = remoteCapabilities;\n transceiver.rtpReceiver = rtpReceiver;\n transceiver.rtcpParameters = rtcpParameters;\n transceiver.sendEncodingParameters = sendEncodingParameters;\n transceiver.recvEncodingParameters = recvEncodingParameters;\n\n // Start the RTCRtpReceiver now. The RTPSender is started in\n // setLocalDescription.\n pc._transceive(pc.transceivers[sdpMLineIndex],\n false,\n isNewTrack);\n } else if (description.type === 'answer' && !rejected) {\n transceiver = pc.transceivers[sdpMLineIndex];\n iceGatherer = transceiver.iceGatherer;\n iceTransport = transceiver.iceTransport;\n dtlsTransport = transceiver.dtlsTransport;\n rtpReceiver = transceiver.rtpReceiver;\n sendEncodingParameters = transceiver.sendEncodingParameters;\n localCapabilities = transceiver.localCapabilities;\n\n pc.transceivers[sdpMLineIndex].recvEncodingParameters =\n recvEncodingParameters;\n pc.transceivers[sdpMLineIndex].remoteCapabilities =\n remoteCapabilities;\n pc.transceivers[sdpMLineIndex].rtcpParameters = rtcpParameters;\n\n if (cands.length && iceTransport.state === 'new') {\n if ((isIceLite || isComplete) &&\n (!usingBundle || sdpMLineIndex === 0)) {\n iceTransport.setRemoteCandidates(cands);\n } else {\n cands.forEach(function(candidate) {\n maybeAddCandidate(transceiver.iceTransport, candidate);\n });\n }\n }\n\n if (!usingBundle || sdpMLineIndex === 0) {\n if (iceTransport.state === 'new') {\n iceTransport.start(iceGatherer, remoteIceParameters,\n 'controlling');\n }\n if (dtlsTransport.state === 'new') {\n dtlsTransport.start(remoteDtlsParameters);\n }\n }\n\n // If the offer contained RTX but the answer did not,\n // remove RTX from sendEncodingParameters.\n var commonCapabilities = getCommonCapabilities(\n transceiver.localCapabilities,\n transceiver.remoteCapabilities);\n\n var hasRtx = commonCapabilities.codecs.filter(function(c) {\n return c.name.toLowerCase() === 'rtx';\n }).length;\n if (!hasRtx && transceiver.sendEncodingParameters[0].rtx) {\n delete transceiver.sendEncodingParameters[0].rtx;\n }\n\n pc._transceive(transceiver,\n direction === 'sendrecv' || direction === 'recvonly',\n direction === 'sendrecv' || direction === 'sendonly');\n\n // TODO: rewrite to use http://w3c.github.io/webrtc-pc/#set-associated-remote-streams\n if (rtpReceiver &&\n (direction === 'sendrecv' || direction === 'sendonly')) {\n track = rtpReceiver.track;\n if (remoteMsid) {\n if (!streams[remoteMsid.stream]) {\n streams[remoteMsid.stream] = new window.MediaStream();\n }\n addTrackToStreamAndFireEvent(track, streams[remoteMsid.stream]);\n receiverList.push([track, rtpReceiver, streams[remoteMsid.stream]]);\n } else {\n if (!streams.default) {\n streams.default = new window.MediaStream();\n }\n addTrackToStreamAndFireEvent(track, streams.default);\n receiverList.push([track, rtpReceiver, streams.default]);\n }\n } else {\n // FIXME: actually the receiver should be created later.\n delete transceiver.rtpReceiver;\n }\n }\n });\n\n if (pc._dtlsRole === undefined) {\n pc._dtlsRole = description.type === 'offer' ? 'active' : 'passive';\n }\n\n pc._remoteDescription = {\n type: description.type,\n sdp: description.sdp\n };\n if (description.type === 'offer') {\n pc._updateSignalingState('have-remote-offer');\n } else {\n pc._updateSignalingState('stable');\n }\n Object.keys(streams).forEach(function(sid) {\n var stream = streams[sid];\n if (stream.getTracks().length) {\n if (pc.remoteStreams.indexOf(stream) === -1) {\n pc.remoteStreams.push(stream);\n var event = new Event('addstream');\n event.stream = stream;\n window.setTimeout(function() {\n pc._dispatchEvent('addstream', event);\n });\n }\n\n receiverList.forEach(function(item) {\n var track = item[0];\n var receiver = item[1];\n if (stream.id !== item[2].id) {\n return;\n }\n fireAddTrack(pc, track, receiver, [stream]);\n });\n }\n });\n receiverList.forEach(function(item) {\n if (item[2]) {\n return;\n }\n fireAddTrack(pc, item[0], item[1], []);\n });\n\n // check whether addIceCandidate({}) was called within four seconds after\n // setRemoteDescription.\n window.setTimeout(function() {\n if (!(pc && pc.transceivers)) {\n return;\n }\n pc.transceivers.forEach(function(transceiver) {\n if (transceiver.iceTransport &&\n transceiver.iceTransport.state === 'new' &&\n transceiver.iceTransport.getRemoteCandidates().length > 0) {\n console.warn('Timeout for addRemoteCandidate. Consider sending ' +\n 'an end-of-candidates notification');\n transceiver.iceTransport.addRemoteCandidate({});\n }\n });\n }, 4000);\n\n return Promise.resolve();\n };\n\n RTCPeerConnection.prototype.close = function() {\n this.transceivers.forEach(function(transceiver) {\n /* not yet\n if (transceiver.iceGatherer) {\n transceiver.iceGatherer.close();\n }\n */\n if (transceiver.iceTransport) {\n transceiver.iceTransport.stop();\n }\n if (transceiver.dtlsTransport) {\n transceiver.dtlsTransport.stop();\n }\n if (transceiver.rtpSender) {\n transceiver.rtpSender.stop();\n }\n if (transceiver.rtpReceiver) {\n transceiver.rtpReceiver.stop();\n }\n });\n // FIXME: clean up tracks, local streams, remote streams, etc\n this._isClosed = true;\n this._updateSignalingState('closed');\n };\n\n // Update the signaling state.\n RTCPeerConnection.prototype._updateSignalingState = function(newState) {\n this.signalingState = newState;\n var event = new Event('signalingstatechange');\n this._dispatchEvent('signalingstatechange', event);\n };\n\n // Determine whether to fire the negotiationneeded event.\n RTCPeerConnection.prototype._maybeFireNegotiationNeeded = function() {\n var pc = this;\n if (this.signalingState !== 'stable' || this.needNegotiation === true) {\n return;\n }\n this.needNegotiation = true;\n window.setTimeout(function() {\n if (pc.needNegotiation) {\n pc.needNegotiation = false;\n var event = new Event('negotiationneeded');\n pc._dispatchEvent('negotiationneeded', event);\n }\n }, 0);\n };\n\n // Update the ice connection state.\n RTCPeerConnection.prototype._updateIceConnectionState = function() {\n var newState;\n var states = {\n 'new': 0,\n closed: 0,\n checking: 0,\n connected: 0,\n completed: 0,\n disconnected: 0,\n failed: 0\n };\n this.transceivers.forEach(function(transceiver) {\n if (transceiver.iceTransport && !transceiver.rejected) {\n states[transceiver.iceTransport.state]++;\n }\n });\n\n newState = 'new';\n if (states.failed > 0) {\n newState = 'failed';\n } else if (states.checking > 0) {\n newState = 'checking';\n } else if (states.disconnected > 0) {\n newState = 'disconnected';\n } else if (states.new > 0) {\n newState = 'new';\n } else if (states.connected > 0) {\n newState = 'connected';\n } else if (states.completed > 0) {\n newState = 'completed';\n }\n\n if (newState !== this.iceConnectionState) {\n this.iceConnectionState = newState;\n var event = new Event('iceconnectionstatechange');\n this._dispatchEvent('iceconnectionstatechange', event);\n }\n };\n\n // Update the connection state.\n RTCPeerConnection.prototype._updateConnectionState = function() {\n var newState;\n var states = {\n 'new': 0,\n closed: 0,\n connecting: 0,\n connected: 0,\n completed: 0,\n disconnected: 0,\n failed: 0\n };\n this.transceivers.forEach(function(transceiver) {\n if (transceiver.iceTransport && transceiver.dtlsTransport &&\n !transceiver.rejected) {\n states[transceiver.iceTransport.state]++;\n states[transceiver.dtlsTransport.state]++;\n }\n });\n // ICETransport.completed and connected are the same for this purpose.\n states.connected += states.completed;\n\n newState = 'new';\n if (states.failed > 0) {\n newState = 'failed';\n } else if (states.connecting > 0) {\n newState = 'connecting';\n } else if (states.disconnected > 0) {\n newState = 'disconnected';\n } else if (states.new > 0) {\n newState = 'new';\n } else if (states.connected > 0) {\n newState = 'connected';\n }\n\n if (newState !== this.connectionState) {\n this.connectionState = newState;\n var event = new Event('connectionstatechange');\n this._dispatchEvent('connectionstatechange', event);\n }\n };\n\n RTCPeerConnection.prototype.createOffer = function() {\n var pc = this;\n\n if (pc._isClosed) {\n return Promise.reject(makeError('InvalidStateError',\n 'Can not call createOffer after close'));\n }\n\n var numAudioTracks = pc.transceivers.filter(function(t) {\n return t.kind === 'audio';\n }).length;\n var numVideoTracks = pc.transceivers.filter(function(t) {\n return t.kind === 'video';\n }).length;\n\n // Determine number of audio and video tracks we need to send/recv.\n var offerOptions = arguments[0];\n if (offerOptions) {\n // Reject Chrome legacy constraints.\n if (offerOptions.mandatory || offerOptions.optional) {\n throw new TypeError(\n 'Legacy mandatory/optional constraints not supported.');\n }\n if (offerOptions.offerToReceiveAudio !== undefined) {\n if (offerOptions.offerToReceiveAudio === true) {\n numAudioTracks = 1;\n } else if (offerOptions.offerToReceiveAudio === false) {\n numAudioTracks = 0;\n } else {\n numAudioTracks = offerOptions.offerToReceiveAudio;\n }\n }\n if (offerOptions.offerToReceiveVideo !== undefined) {\n if (offerOptions.offerToReceiveVideo === true) {\n numVideoTracks = 1;\n } else if (offerOptions.offerToReceiveVideo === false) {\n numVideoTracks = 0;\n } else {\n numVideoTracks = offerOptions.offerToReceiveVideo;\n }\n }\n }\n\n pc.transceivers.forEach(function(transceiver) {\n if (transceiver.kind === 'audio') {\n numAudioTracks--;\n if (numAudioTracks < 0) {\n transceiver.wantReceive = false;\n }\n } else if (transceiver.kind === 'video') {\n numVideoTracks--;\n if (numVideoTracks < 0) {\n transceiver.wantReceive = false;\n }\n }\n });\n\n // Create M-lines for recvonly streams.\n while (numAudioTracks > 0 || numVideoTracks > 0) {\n if (numAudioTracks > 0) {\n pc._createTransceiver('audio');\n numAudioTracks--;\n }\n if (numVideoTracks > 0) {\n pc._createTransceiver('video');\n numVideoTracks--;\n }\n }\n\n var sdp = SDPUtils.writeSessionBoilerplate(pc._sdpSessionId,\n pc._sdpSessionVersion++);\n pc.transceivers.forEach(function(transceiver, sdpMLineIndex) {\n // For each track, create an ice gatherer, ice transport,\n // dtls transport, potentially rtpsender and rtpreceiver.\n var track = transceiver.track;\n var kind = transceiver.kind;\n var mid = transceiver.mid || SDPUtils.generateIdentifier();\n transceiver.mid = mid;\n\n if (!transceiver.iceGatherer) {\n transceiver.iceGatherer = pc._createIceGatherer(sdpMLineIndex,\n pc.usingBundle);\n }\n\n var localCapabilities = window.RTCRtpSender.getCapabilities(kind);\n // filter RTX until additional stuff needed for RTX is implemented\n // in adapter.js\n if (edgeVersion < 15019) {\n localCapabilities.codecs = localCapabilities.codecs.filter(\n function(codec) {\n return codec.name !== 'rtx';\n });\n }\n localCapabilities.codecs.forEach(function(codec) {\n // work around https://bugs.chromium.org/p/webrtc/issues/detail?id=6552\n // by adding level-asymmetry-allowed=1\n if (codec.name === 'H264' &&\n codec.parameters['level-asymmetry-allowed'] === undefined) {\n codec.parameters['level-asymmetry-allowed'] = '1';\n }\n\n // for subsequent offers, we might have to re-use the payload\n // type of the last offer.\n if (transceiver.remoteCapabilities &&\n transceiver.remoteCapabilities.codecs) {\n transceiver.remoteCapabilities.codecs.forEach(function(remoteCodec) {\n if (codec.name.toLowerCase() === remoteCodec.name.toLowerCase() &&\n codec.clockRate === remoteCodec.clockRate) {\n codec.preferredPayloadType = remoteCodec.payloadType;\n }\n });\n }\n });\n localCapabilities.headerExtensions.forEach(function(hdrExt) {\n var remoteExtensions = transceiver.remoteCapabilities &&\n transceiver.remoteCapabilities.headerExtensions || [];\n remoteExtensions.forEach(function(rHdrExt) {\n if (hdrExt.uri === rHdrExt.uri) {\n hdrExt.id = rHdrExt.id;\n }\n });\n });\n\n // generate an ssrc now, to be used later in rtpSender.send\n var sendEncodingParameters = transceiver.sendEncodingParameters || [{\n ssrc: (2 * sdpMLineIndex + 1) * 1001\n }];\n if (track) {\n // add RTX\n if (edgeVersion >= 15019 && kind === 'video' &&\n !sendEncodingParameters[0].rtx) {\n sendEncodingParameters[0].rtx = {\n ssrc: sendEncodingParameters[0].ssrc + 1\n };\n }\n }\n\n if (transceiver.wantReceive) {\n transceiver.rtpReceiver = new window.RTCRtpReceiver(\n transceiver.dtlsTransport, kind);\n }\n\n transceiver.localCapabilities = localCapabilities;\n transceiver.sendEncodingParameters = sendEncodingParameters;\n });\n\n // always offer BUNDLE and dispose on return if not supported.\n if (pc._config.bundlePolicy !== 'max-compat') {\n sdp += 'a=group:BUNDLE ' + pc.transceivers.map(function(t) {\n return t.mid;\n }).join(' ') + '\\r\\n';\n }\n sdp += 'a=ice-options:trickle\\r\\n';\n\n pc.transceivers.forEach(function(transceiver, sdpMLineIndex) {\n sdp += writeMediaSection(transceiver, transceiver.localCapabilities,\n 'offer', transceiver.stream, pc._dtlsRole);\n sdp += 'a=rtcp-rsize\\r\\n';\n\n if (transceiver.iceGatherer && pc.iceGatheringState !== 'new' &&\n (sdpMLineIndex === 0 || !pc.usingBundle)) {\n transceiver.iceGatherer.getLocalCandidates().forEach(function(cand) {\n cand.component = 1;\n sdp += 'a=' + SDPUtils.writeCandidate(cand) + '\\r\\n';\n });\n\n if (transceiver.iceGatherer.state === 'completed') {\n sdp += 'a=end-of-candidates\\r\\n';\n }\n }\n });\n\n var desc = new window.RTCSessionDescription({\n type: 'offer',\n sdp: sdp\n });\n return Promise.resolve(desc);\n };\n\n RTCPeerConnection.prototype.createAnswer = function() {\n var pc = this;\n\n if (pc._isClosed) {\n return Promise.reject(makeError('InvalidStateError',\n 'Can not call createAnswer after close'));\n }\n\n if (!(pc.signalingState === 'have-remote-offer' ||\n pc.signalingState === 'have-local-pranswer')) {\n return Promise.reject(makeError('InvalidStateError',\n 'Can not call createAnswer in signalingState ' + pc.signalingState));\n }\n\n var sdp = SDPUtils.writeSessionBoilerplate(pc._sdpSessionId,\n pc._sdpSessionVersion++);\n if (pc.usingBundle) {\n sdp += 'a=group:BUNDLE ' + pc.transceivers.map(function(t) {\n return t.mid;\n }).join(' ') + '\\r\\n';\n }\n sdp += 'a=ice-options:trickle\\r\\n';\n\n var mediaSectionsInOffer = SDPUtils.getMediaSections(\n pc._remoteDescription.sdp).length;\n pc.transceivers.forEach(function(transceiver, sdpMLineIndex) {\n if (sdpMLineIndex + 1 > mediaSectionsInOffer) {\n return;\n }\n if (transceiver.rejected) {\n if (transceiver.kind === 'application') {\n if (transceiver.protocol === 'DTLS/SCTP') { // legacy fmt\n sdp += 'm=application 0 DTLS/SCTP 5000\\r\\n';\n } else {\n sdp += 'm=application 0 ' + transceiver.protocol +\n ' webrtc-datachannel\\r\\n';\n }\n } else if (transceiver.kind === 'audio') {\n sdp += 'm=audio 0 UDP/TLS/RTP/SAVPF 0\\r\\n' +\n 'a=rtpmap:0 PCMU/8000\\r\\n';\n } else if (transceiver.kind === 'video') {\n sdp += 'm=video 0 UDP/TLS/RTP/SAVPF 120\\r\\n' +\n 'a=rtpmap:120 VP8/90000\\r\\n';\n }\n sdp += 'c=IN IP4 0.0.0.0\\r\\n' +\n 'a=inactive\\r\\n' +\n 'a=mid:' + transceiver.mid + '\\r\\n';\n return;\n }\n\n // FIXME: look at direction.\n if (transceiver.stream) {\n var localTrack;\n if (transceiver.kind === 'audio') {\n localTrack = transceiver.stream.getAudioTracks()[0];\n } else if (transceiver.kind === 'video') {\n localTrack = transceiver.stream.getVideoTracks()[0];\n }\n if (localTrack) {\n // add RTX\n if (edgeVersion >= 15019 && transceiver.kind === 'video' &&\n !transceiver.sendEncodingParameters[0].rtx) {\n transceiver.sendEncodingParameters[0].rtx = {\n ssrc: transceiver.sendEncodingParameters[0].ssrc + 1\n };\n }\n }\n }\n\n // Calculate intersection of capabilities.\n var commonCapabilities = getCommonCapabilities(\n transceiver.localCapabilities,\n transceiver.remoteCapabilities);\n\n var hasRtx = commonCapabilities.codecs.filter(function(c) {\n return c.name.toLowerCase() === 'rtx';\n }).length;\n if (!hasRtx && transceiver.sendEncodingParameters[0].rtx) {\n delete transceiver.sendEncodingParameters[0].rtx;\n }\n\n sdp += writeMediaSection(transceiver, commonCapabilities,\n 'answer', transceiver.stream, pc._dtlsRole);\n if (transceiver.rtcpParameters &&\n transceiver.rtcpParameters.reducedSize) {\n sdp += 'a=rtcp-rsize\\r\\n';\n }\n });\n\n var desc = new window.RTCSessionDescription({\n type: 'answer',\n sdp: sdp\n });\n return Promise.resolve(desc);\n };\n\n RTCPeerConnection.prototype.addIceCandidate = function(candidate) {\n var pc = this;\n var sections;\n if (candidate && !(candidate.sdpMLineIndex !== undefined ||\n candidate.sdpMid)) {\n return Promise.reject(new TypeError('sdpMLineIndex or sdpMid required'));\n }\n\n // TODO: needs to go into ops queue.\n return new Promise(function(resolve, reject) {\n if (!pc._remoteDescription) {\n return reject(makeError('InvalidStateError',\n 'Can not add ICE candidate without a remote description'));\n } else if (!candidate || candidate.candidate === '') {\n for (var j = 0; j < pc.transceivers.length; j++) {\n if (pc.transceivers[j].rejected) {\n continue;\n }\n pc.transceivers[j].iceTransport.addRemoteCandidate({});\n sections = SDPUtils.getMediaSections(pc._remoteDescription.sdp);\n sections[j] += 'a=end-of-candidates\\r\\n';\n pc._remoteDescription.sdp =\n SDPUtils.getDescription(pc._remoteDescription.sdp) +\n sections.join('');\n if (pc.usingBundle) {\n break;\n }\n }\n } else {\n var sdpMLineIndex = candidate.sdpMLineIndex;\n if (candidate.sdpMid) {\n for (var i = 0; i < pc.transceivers.length; i++) {\n if (pc.transceivers[i].mid === candidate.sdpMid) {\n sdpMLineIndex = i;\n break;\n }\n }\n }\n var transceiver = pc.transceivers[sdpMLineIndex];\n if (transceiver) {\n if (transceiver.rejected) {\n return resolve();\n }\n var cand = Object.keys(candidate.candidate).length > 0 ?\n SDPUtils.parseCandidate(candidate.candidate) : {};\n // Ignore Chrome's invalid candidates since Edge does not like them.\n if (cand.protocol === 'tcp' && (cand.port === 0 || cand.port === 9)) {\n return resolve();\n }\n // Ignore RTCP candidates, we assume RTCP-MUX.\n if (cand.component && cand.component !== 1) {\n return resolve();\n }\n // when using bundle, avoid adding candidates to the wrong\n // ice transport. And avoid adding candidates added in the SDP.\n if (sdpMLineIndex === 0 || (sdpMLineIndex > 0 &&\n transceiver.iceTransport !== pc.transceivers[0].iceTransport)) {\n if (!maybeAddCandidate(transceiver.iceTransport, cand)) {\n return reject(makeError('OperationError',\n 'Can not add ICE candidate'));\n }\n }\n\n // update the remoteDescription.\n var candidateString = candidate.candidate.trim();\n if (candidateString.indexOf('a=') === 0) {\n candidateString = candidateString.substr(2);\n }\n sections = SDPUtils.getMediaSections(pc._remoteDescription.sdp);\n sections[sdpMLineIndex] += 'a=' +\n (cand.type ? candidateString : 'end-of-candidates')\n + '\\r\\n';\n pc._remoteDescription.sdp =\n SDPUtils.getDescription(pc._remoteDescription.sdp) +\n sections.join('');\n } else {\n return reject(makeError('OperationError',\n 'Can not add ICE candidate'));\n }\n }\n resolve();\n });\n };\n\n RTCPeerConnection.prototype.getStats = function(selector) {\n if (selector && selector instanceof window.MediaStreamTrack) {\n var senderOrReceiver = null;\n this.transceivers.forEach(function(transceiver) {\n if (transceiver.rtpSender &&\n transceiver.rtpSender.track === selector) {\n senderOrReceiver = transceiver.rtpSender;\n } else if (transceiver.rtpReceiver &&\n transceiver.rtpReceiver.track === selector) {\n senderOrReceiver = transceiver.rtpReceiver;\n }\n });\n if (!senderOrReceiver) {\n throw makeError('InvalidAccessError', 'Invalid selector.');\n }\n return senderOrReceiver.getStats();\n }\n\n var promises = [];\n this.transceivers.forEach(function(transceiver) {\n ['rtpSender', 'rtpReceiver', 'iceGatherer', 'iceTransport',\n 'dtlsTransport'].forEach(function(method) {\n if (transceiver[method]) {\n promises.push(transceiver[method].getStats());\n }\n });\n });\n return Promise.all(promises).then(function(allStats) {\n var results = new Map();\n allStats.forEach(function(stats) {\n stats.forEach(function(stat) {\n results.set(stat.id, stat);\n });\n });\n return results;\n });\n };\n\n // fix low-level stat names and return Map instead of object.\n var ortcObjects = ['RTCRtpSender', 'RTCRtpReceiver', 'RTCIceGatherer',\n 'RTCIceTransport', 'RTCDtlsTransport'];\n ortcObjects.forEach(function(ortcObjectName) {\n var obj = window[ortcObjectName];\n if (obj && obj.prototype && obj.prototype.getStats) {\n var nativeGetstats = obj.prototype.getStats;\n obj.prototype.getStats = function() {\n return nativeGetstats.apply(this)\n .then(function(nativeStats) {\n var mapStats = new Map();\n Object.keys(nativeStats).forEach(function(id) {\n nativeStats[id].type = fixStatsType(nativeStats[id]);\n mapStats.set(id, nativeStats[id]);\n });\n return mapStats;\n });\n };\n }\n });\n\n // legacy callback shims. Should be moved to adapter.js some days.\n var methods = ['createOffer', 'createAnswer'];\n methods.forEach(function(method) {\n var nativeMethod = RTCPeerConnection.prototype[method];\n RTCPeerConnection.prototype[method] = function() {\n var args = arguments;\n if (typeof args[0] === 'function' ||\n typeof args[1] === 'function') { // legacy\n return nativeMethod.apply(this, [arguments[2]])\n .then(function(description) {\n if (typeof args[0] === 'function') {\n args[0].apply(null, [description]);\n }\n }, function(error) {\n if (typeof args[1] === 'function') {\n args[1].apply(null, [error]);\n }\n });\n }\n return nativeMethod.apply(this, arguments);\n };\n });\n\n methods = ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate'];\n methods.forEach(function(method) {\n var nativeMethod = RTCPeerConnection.prototype[method];\n RTCPeerConnection.prototype[method] = function() {\n var args = arguments;\n if (typeof args[1] === 'function' ||\n typeof args[2] === 'function') { // legacy\n return nativeMethod.apply(this, arguments)\n .then(function() {\n if (typeof args[1] === 'function') {\n args[1].apply(null);\n }\n }, function(error) {\n if (typeof args[2] === 'function') {\n args[2].apply(null, [error]);\n }\n });\n }\n return nativeMethod.apply(this, arguments);\n };\n });\n\n // getStats is special. It doesn't have a spec legacy method yet we support\n // getStats(something, cb) without error callbacks.\n ['getStats'].forEach(function(method) {\n var nativeMethod = RTCPeerConnection.prototype[method];\n RTCPeerConnection.prototype[method] = function() {\n var args = arguments;\n if (typeof args[1] === 'function') {\n return nativeMethod.apply(this, arguments)\n .then(function() {\n if (typeof args[1] === 'function') {\n args[1].apply(null);\n }\n });\n }\n return nativeMethod.apply(this, arguments);\n };\n });\n\n return RTCPeerConnection;\n};\n","/*\n * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n /* eslint-env node */\n'use strict';\n\nexport function shimGetUserMedia(window) {\n const navigator = window && window.navigator;\n\n const shimError_ = function(e) {\n return {\n name: {PermissionDeniedError: 'NotAllowedError'}[e.name] || e.name,\n message: e.message,\n constraint: e.constraint,\n toString() {\n return this.name;\n }\n };\n };\n\n // getUserMedia error shim.\n const origGetUserMedia = navigator.mediaDevices.getUserMedia.\n bind(navigator.mediaDevices);\n navigator.mediaDevices.getUserMedia = function(c) {\n return origGetUserMedia(c).catch(e => Promise.reject(shimError_(e)));\n };\n}\n","/*\n * Copyright (c) 2018 The adapter.js project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n /* eslint-env node */\n'use strict';\n\nexport function shimGetDisplayMedia(window) {\n if (!('getDisplayMedia' in window.navigator)) {\n return;\n }\n if (!(window.navigator.mediaDevices)) {\n return;\n }\n if (window.navigator.mediaDevices &&\n 'getDisplayMedia' in window.navigator.mediaDevices) {\n return;\n }\n window.navigator.mediaDevices.getDisplayMedia =\n window.navigator.getDisplayMedia.bind(window.navigator);\n}\n","/*\n * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n/* eslint-env node */\n'use strict';\n\nimport * as utils from '../utils';\nimport {filterIceServers} from './filtericeservers';\nimport shimRTCPeerConnection from 'rtcpeerconnection-shim';\n\nexport {shimGetUserMedia} from './getusermedia';\nexport {shimGetDisplayMedia} from './getdisplaymedia';\n\nexport function shimPeerConnection(window, browserDetails) {\n if (window.RTCIceGatherer) {\n if (!window.RTCIceCandidate) {\n window.RTCIceCandidate = function RTCIceCandidate(args) {\n return args;\n };\n }\n if (!window.RTCSessionDescription) {\n window.RTCSessionDescription = function RTCSessionDescription(args) {\n return args;\n };\n }\n // this adds an additional event listener to MediaStrackTrack that signals\n // when a tracks enabled property was changed. Workaround for a bug in\n // addStream, see below. No longer required in 15025+\n if (browserDetails.version < 15025) {\n const origMSTEnabled = Object.getOwnPropertyDescriptor(\n window.MediaStreamTrack.prototype, 'enabled');\n Object.defineProperty(window.MediaStreamTrack.prototype, 'enabled', {\n set(value) {\n origMSTEnabled.set.call(this, value);\n const ev = new Event('enabled');\n ev.enabled = value;\n this.dispatchEvent(ev);\n }\n });\n }\n }\n\n // ORTC defines the DTMF sender a bit different.\n // https://github.com/w3c/ortc/issues/714\n if (window.RTCRtpSender && !('dtmf' in window.RTCRtpSender.prototype)) {\n Object.defineProperty(window.RTCRtpSender.prototype, 'dtmf', {\n get() {\n if (this._dtmf === undefined) {\n if (this.track.kind === 'audio') {\n this._dtmf = new window.RTCDtmfSender(this);\n } else if (this.track.kind === 'video') {\n this._dtmf = null;\n }\n }\n return this._dtmf;\n }\n });\n }\n // Edge currently only implements the RTCDtmfSender, not the\n // RTCDTMFSender alias. See http://draft.ortc.org/#rtcdtmfsender2*\n if (window.RTCDtmfSender && !window.RTCDTMFSender) {\n window.RTCDTMFSender = window.RTCDtmfSender;\n }\n\n const RTCPeerConnectionShim = shimRTCPeerConnection(window,\n browserDetails.version);\n window.RTCPeerConnection = function RTCPeerConnection(config) {\n if (config && config.iceServers) {\n config.iceServers = filterIceServers(config.iceServers,\n browserDetails.version);\n utils.log('ICE servers after filtering:', config.iceServers);\n }\n return new RTCPeerConnectionShim(config);\n };\n window.RTCPeerConnection.prototype = RTCPeerConnectionShim.prototype;\n}\n\nexport function shimReplaceTrack(window) {\n // ORTC has replaceTrack -- https://github.com/w3c/ortc/issues/614\n if (window.RTCRtpSender &&\n !('replaceTrack' in window.RTCRtpSender.prototype)) {\n window.RTCRtpSender.prototype.replaceTrack =\n window.RTCRtpSender.prototype.setTrack;\n }\n}\n","/*\n * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n/* eslint-env node */\n'use strict';\n\nimport * as utils from '../utils';\n\nexport function shimGetUserMedia(window, browserDetails) {\n const navigator = window && window.navigator;\n const MediaStreamTrack = window && window.MediaStreamTrack;\n\n navigator.getUserMedia = function(constraints, onSuccess, onError) {\n // Replace Firefox 44+'s deprecation warning with unprefixed version.\n utils.deprecated('navigator.getUserMedia',\n 'navigator.mediaDevices.getUserMedia');\n navigator.mediaDevices.getUserMedia(constraints).then(onSuccess, onError);\n };\n\n if (!(browserDetails.version > 55 &&\n 'autoGainControl' in navigator.mediaDevices.getSupportedConstraints())) {\n const remap = function(obj, a, b) {\n if (a in obj && !(b in obj)) {\n obj[b] = obj[a];\n delete obj[a];\n }\n };\n\n const nativeGetUserMedia = navigator.mediaDevices.getUserMedia.\n bind(navigator.mediaDevices);\n navigator.mediaDevices.getUserMedia = function(c) {\n if (typeof c === 'object' && typeof c.audio === 'object') {\n c = JSON.parse(JSON.stringify(c));\n remap(c.audio, 'autoGainControl', 'mozAutoGainControl');\n remap(c.audio, 'noiseSuppression', 'mozNoiseSuppression');\n }\n return nativeGetUserMedia(c);\n };\n\n if (MediaStreamTrack && MediaStreamTrack.prototype.getSettings) {\n const nativeGetSettings = MediaStreamTrack.prototype.getSettings;\n MediaStreamTrack.prototype.getSettings = function() {\n const obj = nativeGetSettings.apply(this, arguments);\n remap(obj, 'mozAutoGainControl', 'autoGainControl');\n remap(obj, 'mozNoiseSuppression', 'noiseSuppression');\n return obj;\n };\n }\n\n if (MediaStreamTrack && MediaStreamTrack.prototype.applyConstraints) {\n const nativeApplyConstraints =\n MediaStreamTrack.prototype.applyConstraints;\n MediaStreamTrack.prototype.applyConstraints = function(c) {\n if (this.kind === 'audio' && typeof c === 'object') {\n c = JSON.parse(JSON.stringify(c));\n remap(c, 'autoGainControl', 'mozAutoGainControl');\n remap(c, 'noiseSuppression', 'mozNoiseSuppression');\n }\n return nativeApplyConstraints.apply(this, [c]);\n };\n }\n }\n}\n","/*\n * Copyright (c) 2018 The adapter.js project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n/* eslint-env node */\n'use strict';\n\nexport function shimGetDisplayMedia(window, preferredMediaSource) {\n if (window.navigator.mediaDevices &&\n 'getDisplayMedia' in window.navigator.mediaDevices) {\n return;\n }\n if (!(window.navigator.mediaDevices)) {\n return;\n }\n window.navigator.mediaDevices.getDisplayMedia =\n function getDisplayMedia(constraints) {\n if (!(constraints && constraints.video)) {\n const err = new DOMException('getDisplayMedia without video ' +\n 'constraints is undefined');\n err.name = 'NotFoundError';\n // from https://heycam.github.io/webidl/#idl-DOMException-error-names\n err.code = 8;\n return Promise.reject(err);\n }\n if (constraints.video === true) {\n constraints.video = {mediaSource: preferredMediaSource};\n } else {\n constraints.video.mediaSource = preferredMediaSource;\n }\n return window.navigator.mediaDevices.getUserMedia(constraints);\n };\n}\n","/*\n * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n/* eslint-env node */\n'use strict';\n\nimport * as utils from '../utils';\nexport {shimGetUserMedia} from './getusermedia';\nexport {shimGetDisplayMedia} from './getdisplaymedia';\n\nexport function shimOnTrack(window) {\n if (typeof window === 'object' && window.RTCTrackEvent &&\n ('receiver' in window.RTCTrackEvent.prototype) &&\n !('transceiver' in window.RTCTrackEvent.prototype)) {\n Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', {\n get() {\n return {receiver: this.receiver};\n }\n });\n }\n}\n\nexport function shimPeerConnection(window, browserDetails) {\n if (typeof window !== 'object' ||\n !(window.RTCPeerConnection || window.mozRTCPeerConnection)) {\n return; // probably media.peerconnection.enabled=false in about:config\n }\n if (!window.RTCPeerConnection && window.mozRTCPeerConnection) {\n // very basic support for old versions.\n window.RTCPeerConnection = window.mozRTCPeerConnection;\n }\n\n if (browserDetails.version < 53) {\n // shim away need for obsolete RTCIceCandidate/RTCSessionDescription.\n ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']\n .forEach(function(method) {\n const nativeMethod = window.RTCPeerConnection.prototype[method];\n const methodObj = {[method]() {\n arguments[0] = new ((method === 'addIceCandidate') ?\n window.RTCIceCandidate :\n window.RTCSessionDescription)(arguments[0]);\n return nativeMethod.apply(this, arguments);\n }};\n window.RTCPeerConnection.prototype[method] = methodObj[method];\n });\n }\n\n const modernStatsTypes = {\n inboundrtp: 'inbound-rtp',\n outboundrtp: 'outbound-rtp',\n candidatepair: 'candidate-pair',\n localcandidate: 'local-candidate',\n remotecandidate: 'remote-candidate'\n };\n\n const nativeGetStats = window.RTCPeerConnection.prototype.getStats;\n window.RTCPeerConnection.prototype.getStats = function getStats() {\n const [selector, onSucc, onErr] = arguments;\n return nativeGetStats.apply(this, [selector || null])\n .then(stats => {\n if (browserDetails.version < 53 && !onSucc) {\n // Shim only promise getStats with spec-hyphens in type names\n // Leave callback version alone; misc old uses of forEach before Map\n try {\n stats.forEach(stat => {\n stat.type = modernStatsTypes[stat.type] || stat.type;\n });\n } catch (e) {\n if (e.name !== 'TypeError') {\n throw e;\n }\n // Avoid TypeError: \"type\" is read-only, in old versions. 34-43ish\n stats.forEach((stat, i) => {\n stats.set(i, Object.assign({}, stat, {\n type: modernStatsTypes[stat.type] || stat.type\n }));\n });\n }\n }\n return stats;\n })\n .then(onSucc, onErr);\n };\n}\n\nexport function shimSenderGetStats(window) {\n if (!(typeof window === 'object' && window.RTCPeerConnection &&\n window.RTCRtpSender)) {\n return;\n }\n if (window.RTCRtpSender && 'getStats' in window.RTCRtpSender.prototype) {\n return;\n }\n const origGetSenders = window.RTCPeerConnection.prototype.getSenders;\n if (origGetSenders) {\n window.RTCPeerConnection.prototype.getSenders = function getSenders() {\n const senders = origGetSenders.apply(this, []);\n senders.forEach(sender => sender._pc = this);\n return senders;\n };\n }\n\n const origAddTrack = window.RTCPeerConnection.prototype.addTrack;\n if (origAddTrack) {\n window.RTCPeerConnection.prototype.addTrack = function addTrack() {\n const sender = origAddTrack.apply(this, arguments);\n sender._pc = this;\n return sender;\n };\n }\n window.RTCRtpSender.prototype.getStats = function getStats() {\n return this.track ? this._pc.getStats(this.track) :\n Promise.resolve(new Map());\n };\n}\n\nexport function shimReceiverGetStats(window) {\n if (!(typeof window === 'object' && window.RTCPeerConnection &&\n window.RTCRtpSender)) {\n return;\n }\n if (window.RTCRtpSender && 'getStats' in window.RTCRtpReceiver.prototype) {\n return;\n }\n const origGetReceivers = window.RTCPeerConnection.prototype.getReceivers;\n if (origGetReceivers) {\n window.RTCPeerConnection.prototype.getReceivers = function getReceivers() {\n const receivers = origGetReceivers.apply(this, []);\n receivers.forEach(receiver => receiver._pc = this);\n return receivers;\n };\n }\n utils.wrapPeerConnectionEvent(window, 'track', e => {\n e.receiver._pc = e.srcElement;\n return e;\n });\n window.RTCRtpReceiver.prototype.getStats = function getStats() {\n return this._pc.getStats(this.track);\n };\n}\n\nexport function shimRemoveStream(window) {\n if (!window.RTCPeerConnection ||\n 'removeStream' in window.RTCPeerConnection.prototype) {\n return;\n }\n window.RTCPeerConnection.prototype.removeStream =\n function removeStream(stream) {\n utils.deprecated('removeStream', 'removeTrack');\n this.getSenders().forEach(sender => {\n if (sender.track && stream.getTracks().includes(sender.track)) {\n this.removeTrack(sender);\n }\n });\n };\n}\n\nexport function shimRTCDataChannel(window) {\n // rename DataChannel to RTCDataChannel (native fix in FF60):\n // https://bugzilla.mozilla.org/show_bug.cgi?id=1173851\n if (window.DataChannel && !window.RTCDataChannel) {\n window.RTCDataChannel = window.DataChannel;\n }\n}\n\nexport function shimAddTransceiver(window) {\n // https://github.com/webrtcHacks/adapter/issues/998#issuecomment-516921647\n // Firefox ignores the init sendEncodings options passed to addTransceiver\n // https://bugzilla.mozilla.org/show_bug.cgi?id=1396918\n if (!(typeof window === 'object' && window.RTCPeerConnection)) {\n return;\n }\n const origAddTransceiver = window.RTCPeerConnection.prototype.addTransceiver;\n if (origAddTransceiver) {\n window.RTCPeerConnection.prototype.addTransceiver =\n function addTransceiver() {\n this.setParametersPromises = [];\n const initParameters = arguments[1];\n const shouldPerformCheck = initParameters &&\n 'sendEncodings' in initParameters;\n if (shouldPerformCheck) {\n // If sendEncodings params are provided, validate grammar\n initParameters.sendEncodings.forEach((encodingParam) => {\n if ('rid' in encodingParam) {\n const ridRegex = /^[a-z0-9]{0,16}$/i;\n if (!ridRegex.test(encodingParam.rid)) {\n throw new TypeError('Invalid RID value provided.');\n }\n }\n if ('scaleResolutionDownBy' in encodingParam) {\n if (!(parseFloat(encodingParam.scaleResolutionDownBy) >= 1.0)) {\n throw new RangeError('scale_resolution_down_by must be >= 1.0');\n }\n }\n if ('maxFramerate' in encodingParam) {\n if (!(parseFloat(encodingParam.maxFramerate) >= 0)) {\n throw new RangeError('max_framerate must be >= 0.0');\n }\n }\n });\n }\n const transceiver = origAddTransceiver.apply(this, arguments);\n if (shouldPerformCheck) {\n // Check if the init options were applied. If not we do this in an\n // asynchronous way and save the promise reference in a global object.\n // This is an ugly hack, but at the same time is way more robust than\n // checking the sender parameters before and after the createOffer\n // Also note that after the createoffer we are not 100% sure that\n // the params were asynchronously applied so we might miss the\n // opportunity to recreate offer.\n const {sender} = transceiver;\n const params = sender.getParameters();\n if (!('encodings' in params) ||\n // Avoid being fooled by patched getParameters() below.\n (params.encodings.length === 1 &&\n Object.keys(params.encodings[0]).length === 0)) {\n params.encodings = initParameters.sendEncodings;\n sender.sendEncodings = initParameters.sendEncodings;\n this.setParametersPromises.push(sender.setParameters(params)\n .then(() => {\n delete sender.sendEncodings;\n }).catch(() => {\n delete sender.sendEncodings;\n })\n );\n }\n }\n return transceiver;\n };\n }\n}\n\nexport function shimGetParameters(window) {\n if (!(typeof window === 'object' && window.RTCRtpSender)) {\n return;\n }\n const origGetParameters = window.RTCRtpSender.prototype.getParameters;\n if (origGetParameters) {\n window.RTCRtpSender.prototype.getParameters =\n function getParameters() {\n const params = origGetParameters.apply(this, arguments);\n if (!('encodings' in params)) {\n params.encodings = [].concat(this.sendEncodings || [{}]);\n }\n return params;\n };\n }\n}\n\nexport function shimCreateOffer(window) {\n // https://github.com/webrtcHacks/adapter/issues/998#issuecomment-516921647\n // Firefox ignores the init sendEncodings options passed to addTransceiver\n // https://bugzilla.mozilla.org/show_bug.cgi?id=1396918\n if (!(typeof window === 'object' && window.RTCPeerConnection)) {\n return;\n }\n const origCreateOffer = window.RTCPeerConnection.prototype.createOffer;\n window.RTCPeerConnection.prototype.createOffer = function createOffer() {\n if (this.setParametersPromises && this.setParametersPromises.length) {\n return Promise.all(this.setParametersPromises)\n .then(() => {\n return origCreateOffer.apply(this, arguments);\n })\n .finally(() => {\n this.setParametersPromises = [];\n });\n }\n return origCreateOffer.apply(this, arguments);\n };\n}\n\nexport function shimCreateAnswer(window) {\n // https://github.com/webrtcHacks/adapter/issues/998#issuecomment-516921647\n // Firefox ignores the init sendEncodings options passed to addTransceiver\n // https://bugzilla.mozilla.org/show_bug.cgi?id=1396918\n if (!(typeof window === 'object' && window.RTCPeerConnection)) {\n return;\n }\n const origCreateAnswer = window.RTCPeerConnection.prototype.createAnswer;\n window.RTCPeerConnection.prototype.createAnswer = function createAnswer() {\n if (this.setParametersPromises && this.setParametersPromises.length) {\n return Promise.all(this.setParametersPromises)\n .then(() => {\n return origCreateAnswer.apply(this, arguments);\n })\n .finally(() => {\n this.setParametersPromises = [];\n });\n }\n return origCreateAnswer.apply(this, arguments);\n };\n}\n","/*\n * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n'use strict';\nimport * as utils from '../utils';\n\nexport function shimLocalStreamsAPI(window) {\n if (typeof window !== 'object' || !window.RTCPeerConnection) {\n return;\n }\n if (!('getLocalStreams' in window.RTCPeerConnection.prototype)) {\n window.RTCPeerConnection.prototype.getLocalStreams =\n function getLocalStreams() {\n if (!this._localStreams) {\n this._localStreams = [];\n }\n return this._localStreams;\n };\n }\n if (!('addStream' in window.RTCPeerConnection.prototype)) {\n const _addTrack = window.RTCPeerConnection.prototype.addTrack;\n window.RTCPeerConnection.prototype.addStream = function addStream(stream) {\n if (!this._localStreams) {\n this._localStreams = [];\n }\n if (!this._localStreams.includes(stream)) {\n this._localStreams.push(stream);\n }\n // Try to emulate Chrome's behaviour of adding in audio-video order.\n // Safari orders by track id.\n stream.getAudioTracks().forEach(track => _addTrack.call(this, track,\n stream));\n stream.getVideoTracks().forEach(track => _addTrack.call(this, track,\n stream));\n };\n\n window.RTCPeerConnection.prototype.addTrack =\n function addTrack(track, ...streams) {\n if (streams) {\n streams.forEach((stream) => {\n if (!this._localStreams) {\n this._localStreams = [stream];\n } else if (!this._localStreams.includes(stream)) {\n this._localStreams.push(stream);\n }\n });\n }\n return _addTrack.apply(this, arguments);\n };\n }\n if (!('removeStream' in window.RTCPeerConnection.prototype)) {\n window.RTCPeerConnection.prototype.removeStream =\n function removeStream(stream) {\n if (!this._localStreams) {\n this._localStreams = [];\n }\n const index = this._localStreams.indexOf(stream);\n if (index === -1) {\n return;\n }\n this._localStreams.splice(index, 1);\n const tracks = stream.getTracks();\n this.getSenders().forEach(sender => {\n if (tracks.includes(sender.track)) {\n this.removeTrack(sender);\n }\n });\n };\n }\n}\n\nexport function shimRemoteStreamsAPI(window) {\n if (typeof window !== 'object' || !window.RTCPeerConnection) {\n return;\n }\n if (!('getRemoteStreams' in window.RTCPeerConnection.prototype)) {\n window.RTCPeerConnection.prototype.getRemoteStreams =\n function getRemoteStreams() {\n return this._remoteStreams ? this._remoteStreams : [];\n };\n }\n if (!('onaddstream' in window.RTCPeerConnection.prototype)) {\n Object.defineProperty(window.RTCPeerConnection.prototype, 'onaddstream', {\n get() {\n return this._onaddstream;\n },\n set(f) {\n if (this._onaddstream) {\n this.removeEventListener('addstream', this._onaddstream);\n this.removeEventListener('track', this._onaddstreampoly);\n }\n this.addEventListener('addstream', this._onaddstream = f);\n this.addEventListener('track', this._onaddstreampoly = (e) => {\n e.streams.forEach(stream => {\n if (!this._remoteStreams) {\n this._remoteStreams = [];\n }\n if (this._remoteStreams.includes(stream)) {\n return;\n }\n this._remoteStreams.push(stream);\n const event = new Event('addstream');\n event.stream = stream;\n this.dispatchEvent(event);\n });\n });\n }\n });\n const origSetRemoteDescription =\n window.RTCPeerConnection.prototype.setRemoteDescription;\n window.RTCPeerConnection.prototype.setRemoteDescription =\n function setRemoteDescription() {\n const pc = this;\n if (!this._onaddstreampoly) {\n this.addEventListener('track', this._onaddstreampoly = function(e) {\n e.streams.forEach(stream => {\n if (!pc._remoteStreams) {\n pc._remoteStreams = [];\n }\n if (pc._remoteStreams.indexOf(stream) >= 0) {\n return;\n }\n pc._remoteStreams.push(stream);\n const event = new Event('addstream');\n event.stream = stream;\n pc.dispatchEvent(event);\n });\n });\n }\n return origSetRemoteDescription.apply(pc, arguments);\n };\n }\n}\n\nexport function shimCallbacksAPI(window) {\n if (typeof window !== 'object' || !window.RTCPeerConnection) {\n return;\n }\n const prototype = window.RTCPeerConnection.prototype;\n const origCreateOffer = prototype.createOffer;\n const origCreateAnswer = prototype.createAnswer;\n const setLocalDescription = prototype.setLocalDescription;\n const setRemoteDescription = prototype.setRemoteDescription;\n const addIceCandidate = prototype.addIceCandidate;\n\n prototype.createOffer =\n function createOffer(successCallback, failureCallback) {\n const options = (arguments.length >= 2) ? arguments[2] : arguments[0];\n const promise = origCreateOffer.apply(this, [options]);\n if (!failureCallback) {\n return promise;\n }\n promise.then(successCallback, failureCallback);\n return Promise.resolve();\n };\n\n prototype.createAnswer =\n function createAnswer(successCallback, failureCallback) {\n const options = (arguments.length >= 2) ? arguments[2] : arguments[0];\n const promise = origCreateAnswer.apply(this, [options]);\n if (!failureCallback) {\n return promise;\n }\n promise.then(successCallback, failureCallback);\n return Promise.resolve();\n };\n\n let withCallback = function(description, successCallback, failureCallback) {\n const promise = setLocalDescription.apply(this, [description]);\n if (!failureCallback) {\n return promise;\n }\n promise.then(successCallback, failureCallback);\n return Promise.resolve();\n };\n prototype.setLocalDescription = withCallback;\n\n withCallback = function(description, successCallback, failureCallback) {\n const promise = setRemoteDescription.apply(this, [description]);\n if (!failureCallback) {\n return promise;\n }\n promise.then(successCallback, failureCallback);\n return Promise.resolve();\n };\n prototype.setRemoteDescription = withCallback;\n\n withCallback = function(candidate, successCallback, failureCallback) {\n const promise = addIceCandidate.apply(this, [candidate]);\n if (!failureCallback) {\n return promise;\n }\n promise.then(successCallback, failureCallback);\n return Promise.resolve();\n };\n prototype.addIceCandidate = withCallback;\n}\n\nexport function shimGetUserMedia(window) {\n const navigator = window && window.navigator;\n\n if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {\n // shim not needed in Safari 12.1\n const mediaDevices = navigator.mediaDevices;\n const _getUserMedia = mediaDevices.getUserMedia.bind(mediaDevices);\n navigator.mediaDevices.getUserMedia = (constraints) => {\n return _getUserMedia(shimConstraints(constraints));\n };\n }\n\n if (!navigator.getUserMedia && navigator.mediaDevices &&\n navigator.mediaDevices.getUserMedia) {\n navigator.getUserMedia = function getUserMedia(constraints, cb, errcb) {\n navigator.mediaDevices.getUserMedia(constraints)\n .then(cb, errcb);\n }.bind(navigator);\n }\n}\n\nexport function shimConstraints(constraints) {\n if (constraints && constraints.video !== undefined) {\n return Object.assign({},\n constraints,\n {video: utils.compactObject(constraints.video)}\n );\n }\n\n return constraints;\n}\n\nexport function shimRTCIceServerUrls(window) {\n if (!window.RTCPeerConnection) {\n return;\n }\n // migrate from non-spec RTCIceServer.url to RTCIceServer.urls\n const OrigPeerConnection = window.RTCPeerConnection;\n window.RTCPeerConnection =\n function RTCPeerConnection(pcConfig, pcConstraints) {\n if (pcConfig && pcConfig.iceServers) {\n const newIceServers = [];\n for (let i = 0; i < pcConfig.iceServers.length; i++) {\n let server = pcConfig.iceServers[i];\n if (!server.hasOwnProperty('urls') &&\n server.hasOwnProperty('url')) {\n utils.deprecated('RTCIceServer.url', 'RTCIceServer.urls');\n server = JSON.parse(JSON.stringify(server));\n server.urls = server.url;\n delete server.url;\n newIceServers.push(server);\n } else {\n newIceServers.push(pcConfig.iceServers[i]);\n }\n }\n pcConfig.iceServers = newIceServers;\n }\n return new OrigPeerConnection(pcConfig, pcConstraints);\n };\n window.RTCPeerConnection.prototype = OrigPeerConnection.prototype;\n // wrap static methods. Currently just generateCertificate.\n if ('generateCertificate' in OrigPeerConnection) {\n Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {\n get() {\n return OrigPeerConnection.generateCertificate;\n }\n });\n }\n}\n\nexport function shimTrackEventTransceiver(window) {\n // Add event.transceiver member over deprecated event.receiver\n if (typeof window === 'object' && window.RTCTrackEvent &&\n 'receiver' in window.RTCTrackEvent.prototype &&\n !('transceiver' in window.RTCTrackEvent.prototype)) {\n Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', {\n get() {\n return {receiver: this.receiver};\n }\n });\n }\n}\n\nexport function shimCreateOfferLegacy(window) {\n const origCreateOffer = window.RTCPeerConnection.prototype.createOffer;\n window.RTCPeerConnection.prototype.createOffer =\n function createOffer(offerOptions) {\n if (offerOptions) {\n if (typeof offerOptions.offerToReceiveAudio !== 'undefined') {\n // support bit values\n offerOptions.offerToReceiveAudio =\n !!offerOptions.offerToReceiveAudio;\n }\n const audioTransceiver = this.getTransceivers().find(transceiver =>\n transceiver.receiver.track.kind === 'audio');\n if (offerOptions.offerToReceiveAudio === false && audioTransceiver) {\n if (audioTransceiver.direction === 'sendrecv') {\n if (audioTransceiver.setDirection) {\n audioTransceiver.setDirection('sendonly');\n } else {\n audioTransceiver.direction = 'sendonly';\n }\n } else if (audioTransceiver.direction === 'recvonly') {\n if (audioTransceiver.setDirection) {\n audioTransceiver.setDirection('inactive');\n } else {\n audioTransceiver.direction = 'inactive';\n }\n }\n } else if (offerOptions.offerToReceiveAudio === true &&\n !audioTransceiver) {\n this.addTransceiver('audio');\n }\n\n if (typeof offerOptions.offerToReceiveVideo !== 'undefined') {\n // support bit values\n offerOptions.offerToReceiveVideo =\n !!offerOptions.offerToReceiveVideo;\n }\n const videoTransceiver = this.getTransceivers().find(transceiver =>\n transceiver.receiver.track.kind === 'video');\n if (offerOptions.offerToReceiveVideo === false && videoTransceiver) {\n if (videoTransceiver.direction === 'sendrecv') {\n if (videoTransceiver.setDirection) {\n videoTransceiver.setDirection('sendonly');\n } else {\n videoTransceiver.direction = 'sendonly';\n }\n } else if (videoTransceiver.direction === 'recvonly') {\n if (videoTransceiver.setDirection) {\n videoTransceiver.setDirection('inactive');\n } else {\n videoTransceiver.direction = 'inactive';\n }\n }\n } else if (offerOptions.offerToReceiveVideo === true &&\n !videoTransceiver) {\n this.addTransceiver('video');\n }\n }\n return origCreateOffer.apply(this, arguments);\n };\n}\n\nexport function shimAudioContext(window) {\n if (typeof window !== 'object' || window.AudioContext) {\n return;\n }\n window.AudioContext = window.webkitAudioContext;\n}\n","/*\n * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n/* eslint-env node */\n'use strict';\n\nimport SDPUtils from 'sdp';\nimport * as utils from './utils';\n\nexport function shimRTCIceCandidate(window) {\n // foundation is arbitrarily chosen as an indicator for full support for\n // https://w3c.github.io/webrtc-pc/#rtcicecandidate-interface\n if (!window.RTCIceCandidate || (window.RTCIceCandidate && 'foundation' in\n window.RTCIceCandidate.prototype)) {\n return;\n }\n\n const NativeRTCIceCandidate = window.RTCIceCandidate;\n window.RTCIceCandidate = function RTCIceCandidate(args) {\n // Remove the a= which shouldn't be part of the candidate string.\n if (typeof args === 'object' && args.candidate &&\n args.candidate.indexOf('a=') === 0) {\n args = JSON.parse(JSON.stringify(args));\n args.candidate = args.candidate.substr(2);\n }\n\n if (args.candidate && args.candidate.length) {\n // Augment the native candidate with the parsed fields.\n const nativeCandidate = new NativeRTCIceCandidate(args);\n const parsedCandidate = SDPUtils.parseCandidate(args.candidate);\n const augmentedCandidate = Object.assign(nativeCandidate,\n parsedCandidate);\n\n // Add a serializer that does not serialize the extra attributes.\n augmentedCandidate.toJSON = function toJSON() {\n return {\n candidate: augmentedCandidate.candidate,\n sdpMid: augmentedCandidate.sdpMid,\n sdpMLineIndex: augmentedCandidate.sdpMLineIndex,\n usernameFragment: augmentedCandidate.usernameFragment,\n };\n };\n return augmentedCandidate;\n }\n return new NativeRTCIceCandidate(args);\n };\n window.RTCIceCandidate.prototype = NativeRTCIceCandidate.prototype;\n\n // Hook up the augmented candidate in onicecandidate and\n // addEventListener('icecandidate', ...)\n utils.wrapPeerConnectionEvent(window, 'icecandidate', e => {\n if (e.candidate) {\n Object.defineProperty(e, 'candidate', {\n value: new window.RTCIceCandidate(e.candidate),\n writable: 'false'\n });\n }\n return e;\n });\n}\n\nexport function shimMaxMessageSize(window, browserDetails) {\n if (!window.RTCPeerConnection) {\n return;\n }\n\n if (!('sctp' in window.RTCPeerConnection.prototype)) {\n Object.defineProperty(window.RTCPeerConnection.prototype, 'sctp', {\n get() {\n return typeof this._sctp === 'undefined' ? null : this._sctp;\n }\n });\n }\n\n const sctpInDescription = function(description) {\n if (!description || !description.sdp) {\n return false;\n }\n const sections = SDPUtils.splitSections(description.sdp);\n sections.shift();\n return sections.some(mediaSection => {\n const mLine = SDPUtils.parseMLine(mediaSection);\n return mLine && mLine.kind === 'application'\n && mLine.protocol.indexOf('SCTP') !== -1;\n });\n };\n\n const getRemoteFirefoxVersion = function(description) {\n // TODO: Is there a better solution for detecting Firefox?\n const match = description.sdp.match(/mozilla...THIS_IS_SDPARTA-(\\d+)/);\n if (match === null || match.length < 2) {\n return -1;\n }\n const version = parseInt(match[1], 10);\n // Test for NaN (yes, this is ugly)\n return version !== version ? -1 : version;\n };\n\n const getCanSendMaxMessageSize = function(remoteIsFirefox) {\n // Every implementation we know can send at least 64 KiB.\n // Note: Although Chrome is technically able to send up to 256 KiB, the\n // data does not reach the other peer reliably.\n // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=8419\n let canSendMaxMessageSize = 65536;\n if (browserDetails.browser === 'firefox') {\n if (browserDetails.version < 57) {\n if (remoteIsFirefox === -1) {\n // FF < 57 will send in 16 KiB chunks using the deprecated PPID\n // fragmentation.\n canSendMaxMessageSize = 16384;\n } else {\n // However, other FF (and RAWRTC) can reassemble PPID-fragmented\n // messages. Thus, supporting ~2 GiB when sending.\n canSendMaxMessageSize = 2147483637;\n }\n } else if (browserDetails.version < 60) {\n // Currently, all FF >= 57 will reset the remote maximum message size\n // to the default value when a data channel is created at a later\n // stage. :(\n // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831\n canSendMaxMessageSize =\n browserDetails.version === 57 ? 65535 : 65536;\n } else {\n // FF >= 60 supports sending ~2 GiB\n canSendMaxMessageSize = 2147483637;\n }\n }\n return canSendMaxMessageSize;\n };\n\n const getMaxMessageSize = function(description, remoteIsFirefox) {\n // Note: 65536 bytes is the default value from the SDP spec. Also,\n // every implementation we know supports receiving 65536 bytes.\n let maxMessageSize = 65536;\n\n // FF 57 has a slightly incorrect default remote max message size, so\n // we need to adjust it here to avoid a failure when sending.\n // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1425697\n if (browserDetails.browser === 'firefox'\n && browserDetails.version === 57) {\n maxMessageSize = 65535;\n }\n\n const match = SDPUtils.matchPrefix(description.sdp,\n 'a=max-message-size:');\n if (match.length > 0) {\n maxMessageSize = parseInt(match[0].substr(19), 10);\n } else if (browserDetails.browser === 'firefox' &&\n remoteIsFirefox !== -1) {\n // If the maximum message size is not present in the remote SDP and\n // both local and remote are Firefox, the remote peer can receive\n // ~2 GiB.\n maxMessageSize = 2147483637;\n }\n return maxMessageSize;\n };\n\n const origSetRemoteDescription =\n window.RTCPeerConnection.prototype.setRemoteDescription;\n window.RTCPeerConnection.prototype.setRemoteDescription =\n function setRemoteDescription() {\n this._sctp = null;\n // Chrome decided to not expose .sctp in plan-b mode.\n // As usual, adapter.js has to do an 'ugly worakaround'\n // to cover up the mess.\n if (browserDetails.browser === 'chrome' && browserDetails.version >= 76) {\n const {sdpSemantics} = this.getConfiguration();\n if (sdpSemantics === 'plan-b') {\n Object.defineProperty(this, 'sctp', {\n get() {\n return typeof this._sctp === 'undefined' ? null : this._sctp;\n },\n enumerable: true,\n configurable: true,\n });\n }\n }\n\n if (sctpInDescription(arguments[0])) {\n // Check if the remote is FF.\n const isFirefox = getRemoteFirefoxVersion(arguments[0]);\n\n // Get the maximum message size the local peer is capable of sending\n const canSendMMS = getCanSendMaxMessageSize(isFirefox);\n\n // Get the maximum message size of the remote peer.\n const remoteMMS = getMaxMessageSize(arguments[0], isFirefox);\n\n // Determine final maximum message size\n let maxMessageSize;\n if (canSendMMS === 0 && remoteMMS === 0) {\n maxMessageSize = Number.POSITIVE_INFINITY;\n } else if (canSendMMS === 0 || remoteMMS === 0) {\n maxMessageSize = Math.max(canSendMMS, remoteMMS);\n } else {\n maxMessageSize = Math.min(canSendMMS, remoteMMS);\n }\n\n // Create a dummy RTCSctpTransport object and the 'maxMessageSize'\n // attribute.\n const sctp = {};\n Object.defineProperty(sctp, 'maxMessageSize', {\n get() {\n return maxMessageSize;\n }\n });\n this._sctp = sctp;\n }\n\n return origSetRemoteDescription.apply(this, arguments);\n };\n}\n\nexport function shimSendThrowTypeError(window) {\n if (!(window.RTCPeerConnection &&\n 'createDataChannel' in window.RTCPeerConnection.prototype)) {\n return;\n }\n\n // Note: Although Firefox >= 57 has a native implementation, the maximum\n // message size can be reset for all data channels at a later stage.\n // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831\n\n function wrapDcSend(dc, pc) {\n const origDataChannelSend = dc.send;\n dc.send = function send() {\n const data = arguments[0];\n const length = data.length || data.size || data.byteLength;\n if (dc.readyState === 'open' &&\n pc.sctp && length > pc.sctp.maxMessageSize) {\n throw new TypeError('Message too large (can send a maximum of ' +\n pc.sctp.maxMessageSize + ' bytes)');\n }\n return origDataChannelSend.apply(dc, arguments);\n };\n }\n const origCreateDataChannel =\n window.RTCPeerConnection.prototype.createDataChannel;\n window.RTCPeerConnection.prototype.createDataChannel =\n function createDataChannel() {\n const dataChannel = origCreateDataChannel.apply(this, arguments);\n wrapDcSend(dataChannel, this);\n return dataChannel;\n };\n utils.wrapPeerConnectionEvent(window, 'datachannel', e => {\n wrapDcSend(e.channel, e.target);\n return e;\n });\n}\n\n\n/* shims RTCConnectionState by pretending it is the same as iceConnectionState.\n * See https://bugs.chromium.org/p/webrtc/issues/detail?id=6145#c12\n * for why this is a valid hack in Chrome. In Firefox it is slightly incorrect\n * since DTLS failures would be hidden. See\n * https://bugzilla.mozilla.org/show_bug.cgi?id=1265827\n * for the Firefox tracking bug.\n */\nexport function shimConnectionState(window) {\n if (!window.RTCPeerConnection ||\n 'connectionState' in window.RTCPeerConnection.prototype) {\n return;\n }\n const proto = window.RTCPeerConnection.prototype;\n Object.defineProperty(proto, 'connectionState', {\n get() {\n return {\n completed: 'connected',\n checking: 'connecting'\n }[this.iceConnectionState] || this.iceConnectionState;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(proto, 'onconnectionstatechange', {\n get() {\n return this._onconnectionstatechange || null;\n },\n set(cb) {\n if (this._onconnectionstatechange) {\n this.removeEventListener('connectionstatechange',\n this._onconnectionstatechange);\n delete this._onconnectionstatechange;\n }\n if (cb) {\n this.addEventListener('connectionstatechange',\n this._onconnectionstatechange = cb);\n }\n },\n enumerable: true,\n configurable: true\n });\n\n ['setLocalDescription', 'setRemoteDescription'].forEach((method) => {\n const origMethod = proto[method];\n proto[method] = function() {\n if (!this._connectionstatechangepoly) {\n this._connectionstatechangepoly = e => {\n const pc = e.target;\n if (pc._lastConnectionState !== pc.connectionState) {\n pc._lastConnectionState = pc.connectionState;\n const newEvent = new Event('connectionstatechange', e);\n pc.dispatchEvent(newEvent);\n }\n return e;\n };\n this.addEventListener('iceconnectionstatechange',\n this._connectionstatechangepoly);\n }\n return origMethod.apply(this, arguments);\n };\n });\n}\n\nexport function removeExtmapAllowMixed(window, browserDetails) {\n /* remove a=extmap-allow-mixed for webrtc.org < M71 */\n if (!window.RTCPeerConnection) {\n return;\n }\n if (browserDetails.browser === 'chrome' && browserDetails.version >= 71) {\n return;\n }\n if (browserDetails.browser === 'safari' && browserDetails.version >= 605) {\n return;\n }\n const nativeSRD = window.RTCPeerConnection.prototype.setRemoteDescription;\n window.RTCPeerConnection.prototype.setRemoteDescription =\n function setRemoteDescription(desc) {\n if (desc && desc.sdp && desc.sdp.indexOf('\\na=extmap-allow-mixed') !== -1) {\n const sdp = desc.sdp.split('\\n').filter((line) => {\n return line.trim() !== 'a=extmap-allow-mixed';\n }).join('\\n');\n // Safari enforces read-only-ness of RTCSessionDescription fields.\n if (window.RTCSessionDescription &&\n desc instanceof window.RTCSessionDescription) {\n arguments[0] = new window.RTCSessionDescription({\n type: desc.type,\n sdp,\n });\n } else {\n desc.sdp = sdp;\n }\n }\n return nativeSRD.apply(this, arguments);\n };\n}\n\nexport function shimAddIceCandidateNullOrEmpty(window, browserDetails) {\n // Support for addIceCandidate(null or undefined)\n // as well as addIceCandidate({candidate: \"\", ...})\n // https://bugs.chromium.org/p/chromium/issues/detail?id=978582\n // Note: must be called before other polyfills which change the signature.\n if (!(window.RTCPeerConnection && window.RTCPeerConnection.prototype)) {\n return;\n }\n const nativeAddIceCandidate =\n window.RTCPeerConnection.prototype.addIceCandidate;\n if (!nativeAddIceCandidate || nativeAddIceCandidate.length === 0) {\n return;\n }\n window.RTCPeerConnection.prototype.addIceCandidate =\n function addIceCandidate() {\n if (!arguments[0]) {\n if (arguments[1]) {\n arguments[1].apply(null);\n }\n return Promise.resolve();\n }\n // Firefox 68+ emits and processes {candidate: \"\", ...}, ignore\n // in older versions.\n // Native support for ignoring exists for Chrome M77+.\n // Safari ignores as well, exact version unknown but works in the same\n // version that also ignores addIceCandidate(null).\n if (((browserDetails.browser === 'chrome' && browserDetails.version < 78)\n || (browserDetails.browser === 'firefox'\n && browserDetails.version < 68)\n || (browserDetails.browser === 'safari'))\n && arguments[0] && arguments[0].candidate === '') {\n return Promise.resolve();\n }\n return nativeAddIceCandidate.apply(this, arguments);\n };\n}\n","/*\n * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\nimport * as utils from './utils';\n\n // Browser shims.\nimport * as chromeShim from './chrome/chrome_shim';\nimport * as edgeShim from './edge/edge_shim';\nimport * as firefoxShim from './firefox/firefox_shim';\nimport * as safariShim from './safari/safari_shim';\nimport * as commonShim from './common_shim';\n\n// Shimming starts here.\nexport function adapterFactory({window} = {}, options = {\n shimChrome: true,\n shimFirefox: true,\n shimEdge: true,\n shimSafari: true,\n}) {\n // Utils.\n const logging = utils.log;\n const browserDetails = utils.detectBrowser(window);\n\n const adapter = {\n browserDetails,\n commonShim,\n extractVersion: utils.extractVersion,\n disableLog: utils.disableLog,\n disableWarnings: utils.disableWarnings\n };\n\n // Shim browser if found.\n switch (browserDetails.browser) {\n case 'chrome':\n if (!chromeShim || !chromeShim.shimPeerConnection ||\n !options.shimChrome) {\n logging('Chrome shim is not included in this adapter release.');\n return adapter;\n }\n if (browserDetails.version === null) {\n logging('Chrome shim can not determine version, not shimming.');\n return adapter;\n }\n logging('adapter.js shimming chrome.');\n // Export to the adapter global object visible in the browser.\n adapter.browserShim = chromeShim;\n\n // Must be called before shimPeerConnection.\n commonShim.shimAddIceCandidateNullOrEmpty(window, browserDetails);\n\n chromeShim.shimGetUserMedia(window, browserDetails);\n chromeShim.shimMediaStream(window, browserDetails);\n chromeShim.shimPeerConnection(window, browserDetails);\n chromeShim.shimOnTrack(window, browserDetails);\n chromeShim.shimAddTrackRemoveTrack(window, browserDetails);\n chromeShim.shimGetSendersWithDtmf(window, browserDetails);\n chromeShim.shimGetStats(window, browserDetails);\n chromeShim.shimSenderReceiverGetStats(window, browserDetails);\n chromeShim.fixNegotiationNeeded(window, browserDetails);\n\n commonShim.shimRTCIceCandidate(window, browserDetails);\n commonShim.shimConnectionState(window, browserDetails);\n commonShim.shimMaxMessageSize(window, browserDetails);\n commonShim.shimSendThrowTypeError(window, browserDetails);\n commonShim.removeExtmapAllowMixed(window, browserDetails);\n break;\n case 'firefox':\n if (!firefoxShim || !firefoxShim.shimPeerConnection ||\n !options.shimFirefox) {\n logging('Firefox shim is not included in this adapter release.');\n return adapter;\n }\n logging('adapter.js shimming firefox.');\n // Export to the adapter global object visible in the browser.\n adapter.browserShim = firefoxShim;\n\n // Must be called before shimPeerConnection.\n commonShim.shimAddIceCandidateNullOrEmpty(window, browserDetails);\n\n firefoxShim.shimGetUserMedia(window, browserDetails);\n firefoxShim.shimPeerConnection(window, browserDetails);\n firefoxShim.shimOnTrack(window, browserDetails);\n firefoxShim.shimRemoveStream(window, browserDetails);\n firefoxShim.shimSenderGetStats(window, browserDetails);\n firefoxShim.shimReceiverGetStats(window, browserDetails);\n firefoxShim.shimRTCDataChannel(window, browserDetails);\n firefoxShim.shimAddTransceiver(window, browserDetails);\n firefoxShim.shimGetParameters(window, browserDetails);\n firefoxShim.shimCreateOffer(window, browserDetails);\n firefoxShim.shimCreateAnswer(window, browserDetails);\n\n commonShim.shimRTCIceCandidate(window, browserDetails);\n commonShim.shimConnectionState(window, browserDetails);\n commonShim.shimMaxMessageSize(window, browserDetails);\n commonShim.shimSendThrowTypeError(window, browserDetails);\n break;\n case 'edge':\n if (!edgeShim || !edgeShim.shimPeerConnection || !options.shimEdge) {\n logging('MS edge shim is not included in this adapter release.');\n return adapter;\n }\n logging('adapter.js shimming edge.');\n // Export to the adapter global object visible in the browser.\n adapter.browserShim = edgeShim;\n\n edgeShim.shimGetUserMedia(window, browserDetails);\n edgeShim.shimGetDisplayMedia(window, browserDetails);\n edgeShim.shimPeerConnection(window, browserDetails);\n edgeShim.shimReplaceTrack(window, browserDetails);\n\n // the edge shim implements the full RTCIceCandidate object.\n\n commonShim.shimMaxMessageSize(window, browserDetails);\n commonShim.shimSendThrowTypeError(window, browserDetails);\n break;\n case 'safari':\n if (!safariShim || !options.shimSafari) {\n logging('Safari shim is not included in this adapter release.');\n return adapter;\n }\n logging('adapter.js shimming safari.');\n // Export to the adapter global object visible in the browser.\n adapter.browserShim = safariShim;\n\n // Must be called before shimCallbackAPI.\n commonShim.shimAddIceCandidateNullOrEmpty(window, browserDetails);\n\n safariShim.shimRTCIceServerUrls(window, browserDetails);\n safariShim.shimCreateOfferLegacy(window, browserDetails);\n safariShim.shimCallbacksAPI(window, browserDetails);\n safariShim.shimLocalStreamsAPI(window, browserDetails);\n safariShim.shimRemoteStreamsAPI(window, browserDetails);\n safariShim.shimTrackEventTransceiver(window, browserDetails);\n safariShim.shimGetUserMedia(window, browserDetails);\n safariShim.shimAudioContext(window, browserDetails);\n\n commonShim.shimRTCIceCandidate(window, browserDetails);\n commonShim.shimMaxMessageSize(window, browserDetails);\n commonShim.shimSendThrowTypeError(window, browserDetails);\n commonShim.removeExtmapAllowMixed(window, browserDetails);\n break;\n default:\n logging('Unsupported browser!');\n break;\n }\n\n return adapter;\n}\n","/*\n * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n/* eslint-env node */\n\n'use strict';\n\nimport {adapterFactory} from './adapter_factory.js';\n\nconst adapter =\n adapterFactory({window: typeof window === 'undefined' ? undefined : window});\nexport default adapter;\n","\n'use strict';\nimport * as utils from './utils.js';\nimport * as MediaFormatModule from './mediaformat.js';\nimport adapter from 'webrtc-adapter';\n\n/**\n * @class AudioTrackConstraints\n * @classDesc Constraints for creating an audio MediaStreamTrack.\n * @memberof Owt.Base\n * @constructor\n * @param {Owt.Base.AudioSourceInfo} source Source info of this audio track.\n */\nexport class AudioTrackConstraints {\n // eslint-disable-next-line require-jsdoc\n constructor(source) {\n if (!Object.values(MediaFormatModule.AudioSourceInfo)\n .some((v) => v === source)) {\n throw new TypeError('Invalid source.');\n }\n /**\n * @member {string} source\n * @memberof Owt.Base.AudioTrackConstraints\n * @desc Values could be \"mic\", \"screen-cast\", \"file\" or \"mixed\".\n * @instance\n */\n this.source = source;\n /**\n * @member {string} deviceId\n * @memberof Owt.Base.AudioTrackConstraints\n * @desc Do not provide deviceId if source is not \"mic\".\n * @instance\n * @see https://w3c.github.io/mediacapture-main/#def-constraint-deviceId\n */\n this.deviceId = undefined;\n }\n}\n\n/**\n * @class VideoTrackConstraints\n * @classDesc Constraints for creating a video MediaStreamTrack.\n * @memberof Owt.Base\n * @constructor\n * @param {Owt.Base.VideoSourceInfo} source Source info of this video track.\n */\nexport class VideoTrackConstraints {\n // eslint-disable-next-line require-jsdoc\n constructor(source) {\n if (!Object.values(MediaFormatModule.VideoSourceInfo)\n .some((v) => v === source)) {\n throw new TypeError('Invalid source.');\n }\n /**\n * @member {string} source\n * @memberof Owt.Base.VideoTrackConstraints\n * @desc Values could be \"camera\", \"screen-cast\", \"file\" or \"mixed\".\n * @instance\n */\n this.source = source;\n /**\n * @member {string} deviceId\n * @memberof Owt.Base.VideoTrackConstraints\n * @desc Do not provide deviceId if source is not \"camera\".\n * @instance\n * @see https://w3c.github.io/mediacapture-main/#def-constraint-deviceId\n */\n\n this.deviceId = undefined;\n\n /**\n * @member {Owt.Base.Resolution} resolution\n * @memberof Owt.Base.VideoTrackConstraints\n * @instance\n */\n this.resolution = undefined;\n\n /**\n * @member {number} frameRate\n * @memberof Owt.Base.VideoTrackConstraints\n * @instance\n */\n this.frameRate = undefined;\n }\n}\n/**\n * @class StreamConstraints\n * @classDesc Constraints for creating a MediaStream from screen mic and camera.\n * @memberof Owt.Base\n * @constructor\n * @param {?Owt.Base.AudioTrackConstraints} audioConstraints\n * @param {?Owt.Base.VideoTrackConstraints} videoConstraints\n */\nexport class StreamConstraints {\n // eslint-disable-next-line require-jsdoc\n constructor(audioConstraints = false, videoConstraints = false) {\n /**\n * @member {Owt.Base.MediaStreamTrackDeviceConstraintsForAudio} audio\n * @memberof Owt.Base.MediaStreamDeviceConstraints\n * @instance\n */\n this.audio = audioConstraints;\n /**\n * @member {Owt.Base.MediaStreamTrackDeviceConstraintsForVideo} Video\n * @memberof Owt.Base.MediaStreamDeviceConstraints\n * @instance\n */\n this.video = videoConstraints;\n }\n}\n\n// eslint-disable-next-line require-jsdoc\nfunction isVideoConstrainsForScreenCast(constraints) {\n return (typeof constraints.video === 'object' && constraints.video.source ===\n MediaFormatModule.VideoSourceInfo.SCREENCAST);\n}\n\n/**\n * @class MediaStreamFactory\n * @classDesc A factory to create MediaStream. You can also create MediaStream by yourself.\n * @memberof Owt.Base\n */\nexport class MediaStreamFactory {\n /**\n * @function createMediaStream\n * @static\n * @desc Create a MediaStream with given constraints. If you want to create a MediaStream for screen cast, please make sure both audio and video's source are \"screen-cast\".\n * @memberof Owt.Base.MediaStreamFactory\n * @return {Promise<MediaStream, Error>} Return a promise that is resolved when stream is successfully created, or rejected if one of the following error happened:\n * - One or more parameters cannot be satisfied.\n * - Specified device is busy.\n * - Cannot obtain necessary permission or operation is canceled by user.\n * - Video source is screen cast, while audio source is not.\n * - Audio source is screen cast, while video source is disabled.\n * @param {Owt.Base.StreamConstraints} constraints\n */\n static createMediaStream(constraints) {\n if (typeof constraints !== 'object' ||\n (!constraints.audio && !constraints.video)) {\n return Promise.reject(new TypeError('Invalid constrains'));\n }\n if (!isVideoConstrainsForScreenCast(constraints) &&\n (typeof constraints.audio === 'object') &&\n constraints.audio.source ===\n MediaFormatModule.AudioSourceInfo.SCREENCAST) {\n return Promise.reject(\n new TypeError('Cannot share screen without video.'));\n }\n if (isVideoConstrainsForScreenCast(constraints) && !utils.isChrome() &&\n !utils.isFirefox()) {\n return Promise.reject(\n new TypeError('Screen sharing only supports Chrome and Firefox.'));\n }\n if (isVideoConstrainsForScreenCast(constraints) &&\n typeof constraints.audio === 'object' &&\n constraints.audio.source !==\n MediaFormatModule.AudioSourceInfo.SCREENCAST) {\n return Promise.reject(new TypeError(\n 'Cannot capture video from screen cast while capture audio from'\n + ' other source.'));\n }\n\n // Check and convert constraints.\n if (!constraints.audio && !constraints.video) {\n return Promise.reject(new TypeError(\n 'At least one of audio and video must be requested.'));\n }\n const mediaConstraints = Object.create({});\n if (typeof constraints.audio === 'object' &&\n constraints.audio.source === MediaFormatModule.AudioSourceInfo.MIC) {\n mediaConstraints.audio = Object.create({});\n if (utils.isEdge()) {\n mediaConstraints.audio.deviceId = constraints.audio.deviceId;\n } else {\n mediaConstraints.audio.deviceId = {\n exact: constraints.audio.deviceId,\n };\n }\n } else {\n if (constraints.audio.source ===\n MediaFormatModule.AudioSourceInfo.SCREENCAST) {\n mediaConstraints.audio = true;\n } else {\n mediaConstraints.audio = constraints.audio;\n }\n }\n if (typeof constraints.video === 'object') {\n mediaConstraints.video = Object.create({});\n if (typeof constraints.video.frameRate === 'number') {\n mediaConstraints.video.frameRate = constraints.video.frameRate;\n }\n if (constraints.video.resolution &&\n constraints.video.resolution.width &&\n constraints.video.resolution.height) {\n if (constraints.video.source ===\n MediaFormatModule.VideoSourceInfo.SCREENCAST) {\n mediaConstraints.video.width = constraints.video.resolution.width;\n mediaConstraints.video.height = constraints.video.resolution.height;\n } else {\n mediaConstraints.video.width = Object.create({});\n mediaConstraints.video.width.exact =\n constraints.video.resolution.width;\n mediaConstraints.video.height = Object.create({});\n mediaConstraints.video.height.exact =\n constraints.video.resolution.height;\n }\n }\n if (typeof constraints.video.deviceId === 'string') {\n mediaConstraints.video.deviceId = {exact: constraints.video.deviceId};\n }\n if (utils.isFirefox() &&\n constraints.video.source ===\n MediaFormatModule.VideoSourceInfo.SCREENCAST) {\n mediaConstraints.video.mediaSource = 'screen';\n }\n } else {\n mediaConstraints.video = constraints.video;\n }\n\n if (isVideoConstrainsForScreenCast(constraints)) {\n return navigator.mediaDevices.getDisplayMedia(mediaConstraints);\n } else {\n return navigator.mediaDevices.getUserMedia(mediaConstraints);\n }\n }\n}\n","// Copyright (C) <2018> Intel Corporation\n//\n// SPDX-License-Identifier: Apache-2.0\n\n'use strict';\n\nexport * from './mediastream-factory.js';\nexport * from './mediaformat.js';","let logger;\nlet errorLogger;\n\nexport function setLogger() {\n /*eslint-disable */\n logger = console.log;\n errorLogger = console.error;\n /*eslint-enable */\n}\n\nexport function isEnable() {\n return logger != null;\n}\n\nexport function log(message, ...optionalParams) {\n if (logger) {\n logger(message, ...optionalParams);\n }\n}\nexport function error(message, ...optionalParams) {\n if (errorLogger) {\n errorLogger(message, ...optionalParams);\n }\n}\n","export default class Event {\n constructor(type) {\n this.listener = {};\n this.type = type | '';\n }\n\n on(event, fn) {\n if (!this.listener[event]) {\n this.listener[event] = [];\n }\n this.listener[event].push(fn);\n return true;\n }\n\n off(event, fn) {\n if (this.listener[event]) {\n var index = this.listener[event].indexOf(fn);\n if (index > -1) {\n this.listener[event].splice(index, 1);\n }\n return true;\n }\n return false;\n }\n\n offAll() {\n this.listener = {};\n }\n\n dispatch(event, data) {\n if (this.listener[event]) {\n this.listener[event].map((each) => {\n each.apply(null, [data]);\n });\n return true;\n }\n return false;\n }\n}\n","'use strict';\n\nmodule.exports = function bind(fn, thisArg) {\n return function wrap() {\n var args = new Array(arguments.length);\n for (var i = 0; i < args.length; i++) {\n args[i] = arguments[i];\n }\n return fn.apply(thisArg, args);\n };\n};\n","'use strict';\n\nvar bind = require('./helpers/bind');\n\n/*global toString:true*/\n\n// utils is a library of generic helper functions non-specific to axios\n\nvar toString = Object.prototype.toString;\n\n/**\n * Determine if a value is an Array\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is an Array, otherwise false\n */\nfunction isArray(val) {\n return toString.call(val) === '[object Array]';\n}\n\n/**\n * Determine if a value is undefined\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if the value is undefined, otherwise false\n */\nfunction isUndefined(val) {\n return typeof val === 'undefined';\n}\n\n/**\n * Determine if a value is a Buffer\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Buffer, otherwise false\n */\nfunction isBuffer(val) {\n return val !== null && !isUndefined(val) && val.constructor !== null && !isUndefined(val.constructor)\n && typeof val.constructor.isBuffer === 'function' && val.constructor.isBuffer(val);\n}\n\n/**\n * Determine if a value is an ArrayBuffer\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is an ArrayBuffer, otherwise false\n */\nfunction isArrayBuffer(val) {\n return toString.call(val) === '[object ArrayBuffer]';\n}\n\n/**\n * Determine if a value is a FormData\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is an FormData, otherwise false\n */\nfunction isFormData(val) {\n return (typeof FormData !== 'undefined') && (val instanceof FormData);\n}\n\n/**\n * Determine if a value is a view on an ArrayBuffer\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false\n */\nfunction isArrayBufferView(val) {\n var result;\n if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) {\n result = ArrayBuffer.isView(val);\n } else {\n result = (val) && (val.buffer) && (val.buffer instanceof ArrayBuffer);\n }\n return result;\n}\n\n/**\n * Determine if a value is a String\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a String, otherwise false\n */\nfunction isString(val) {\n return typeof val === 'string';\n}\n\n/**\n * Determine if a value is a Number\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Number, otherwise false\n */\nfunction isNumber(val) {\n return typeof val === 'number';\n}\n\n/**\n * Determine if a value is an Object\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is an Object, otherwise false\n */\nfunction isObject(val) {\n return val !== null && typeof val === 'object';\n}\n\n/**\n * Determine if a value is a plain Object\n *\n * @param {Object} val The value to test\n * @return {boolean} True if value is a plain Object, otherwise false\n */\nfunction isPlainObject(val) {\n if (toString.call(val) !== '[object Object]') {\n return false;\n }\n\n var prototype = Object.getPrototypeOf(val);\n return prototype === null || prototype === Object.prototype;\n}\n\n/**\n * Determine if a value is a Date\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Date, otherwise false\n */\nfunction isDate(val) {\n return toString.call(val) === '[object Date]';\n}\n\n/**\n * Determine if a value is a File\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a File, otherwise false\n */\nfunction isFile(val) {\n return toString.call(val) === '[object File]';\n}\n\n/**\n * Determine if a value is a Blob\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Blob, otherwise false\n */\nfunction isBlob(val) {\n return toString.call(val) === '[object Blob]';\n}\n\n/**\n * Determine if a value is a Function\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Function, otherwise false\n */\nfunction isFunction(val) {\n return toString.call(val) === '[object Function]';\n}\n\n/**\n * Determine if a value is a Stream\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Stream, otherwise false\n */\nfunction isStream(val) {\n return isObject(val) && isFunction(val.pipe);\n}\n\n/**\n * Determine if a value is a URLSearchParams object\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a URLSearchParams object, otherwise false\n */\nfunction isURLSearchParams(val) {\n return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams;\n}\n\n/**\n * Trim excess whitespace off the beginning and end of a string\n *\n * @param {String} str The String to trim\n * @returns {String} The String freed of excess whitespace\n */\nfunction trim(str) {\n return str.replace(/^\\s*/, '').replace(/\\s*$/, '');\n}\n\n/**\n * Determine if we're running in a standard browser environment\n *\n * This allows axios to run in a web worker, and react-native.\n * Both environments support XMLHttpRequest, but not fully standard globals.\n *\n * web workers:\n * typeof window -> undefined\n * typeof document -> undefined\n *\n * react-native:\n * navigator.product -> 'ReactNative'\n * nativescript\n * navigator.product -> 'NativeScript' or 'NS'\n */\nfunction isStandardBrowserEnv() {\n if (typeof navigator !== 'undefined' && (navigator.product === 'ReactNative' ||\n navigator.product === 'NativeScript' ||\n navigator.product === 'NS')) {\n return false;\n }\n return (\n typeof window !== 'undefined' &&\n typeof document !== 'undefined'\n );\n}\n\n/**\n * Iterate over an Array or an Object invoking a function for each item.\n *\n * If `obj` is an Array callback will be called passing\n * the value, index, and complete array for each item.\n *\n * If 'obj' is an Object callback will be called passing\n * the value, key, and complete object for each property.\n *\n * @param {Object|Array} obj The object to iterate\n * @param {Function} fn The callback to invoke for each item\n */\nfunction forEach(obj, fn) {\n // Don't bother if no value provided\n if (obj === null || typeof obj === 'undefined') {\n return;\n }\n\n // Force an array if not already something iterable\n if (typeof obj !== 'object') {\n /*eslint no-param-reassign:0*/\n obj = [obj];\n }\n\n if (isArray(obj)) {\n // Iterate over array values\n for (var i = 0, l = obj.length; i < l; i++) {\n fn.call(null, obj[i], i, obj);\n }\n } else {\n // Iterate over object keys\n for (var key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n fn.call(null, obj[key], key, obj);\n }\n }\n }\n}\n\n/**\n * Accepts varargs expecting each argument to be an object, then\n * immutably merges the properties of each object and returns result.\n *\n * When multiple objects contain the same key the later object in\n * the arguments list will take precedence.\n *\n * Example:\n *\n * ```js\n * var result = merge({foo: 123}, {foo: 456});\n * console.log(result.foo); // outputs 456\n * ```\n *\n * @param {Object} obj1 Object to merge\n * @returns {Object} Result of all merge properties\n */\nfunction merge(/* obj1, obj2, obj3, ... */) {\n var result = {};\n function assignValue(val, key) {\n if (isPlainObject(result[key]) && isPlainObject(val)) {\n result[key] = merge(result[key], val);\n } else if (isPlainObject(val)) {\n result[key] = merge({}, val);\n } else if (isArray(val)) {\n result[key] = val.slice();\n } else {\n result[key] = val;\n }\n }\n\n for (var i = 0, l = arguments.length; i < l; i++) {\n forEach(arguments[i], assignValue);\n }\n return result;\n}\n\n/**\n * Extends object a by mutably adding to it the properties of object b.\n *\n * @param {Object} a The object to be extended\n * @param {Object} b The object to copy properties from\n * @param {Object} thisArg The object to bind function to\n * @return {Object} The resulting value of object a\n */\nfunction extend(a, b, thisArg) {\n forEach(b, function assignValue(val, key) {\n if (thisArg && typeof val === 'function') {\n a[key] = bind(val, thisArg);\n } else {\n a[key] = val;\n }\n });\n return a;\n}\n\n/**\n * Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)\n *\n * @param {string} content with BOM\n * @return {string} content value without BOM\n */\nfunction stripBOM(content) {\n if (content.charCodeAt(0) === 0xFEFF) {\n content = content.slice(1);\n }\n return content;\n}\n\nmodule.exports = {\n isArray: isArray,\n isArrayBuffer: isArrayBuffer,\n isBuffer: isBuffer,\n isFormData: isFormData,\n isArrayBufferView: isArrayBufferView,\n isString: isString,\n isNumber: isNumber,\n isObject: isObject,\n isPlainObject: isPlainObject,\n isUndefined: isUndefined,\n isDate: isDate,\n isFile: isFile,\n isBlob: isBlob,\n isFunction: isFunction,\n isStream: isStream,\n isURLSearchParams: isURLSearchParams,\n isStandardBrowserEnv: isStandardBrowserEnv,\n forEach: forEach,\n merge: merge,\n extend: extend,\n trim: trim,\n stripBOM: stripBOM\n};\n","'use strict';\n\nvar utils = require('./../utils');\n\nfunction encode(val) {\n return encodeURIComponent(val).\n replace(/%3A/gi, ':').\n replace(/%24/g, '$').\n replace(/%2C/gi, ',').\n replace(/%20/g, '+').\n replace(/%5B/gi, '[').\n replace(/%5D/gi, ']');\n}\n\n/**\n * Build a URL by appending params to the end\n *\n * @param {string} url The base of the url (e.g., http://www.google.com)\n * @param {object} [params] The params to be appended\n * @returns {string} The formatted url\n */\nmodule.exports = function buildURL(url, params, paramsSerializer) {\n /*eslint no-param-reassign:0*/\n if (!params) {\n return url;\n }\n\n var serializedParams;\n if (paramsSerializer) {\n serializedParams = paramsSerializer(params);\n } else if (utils.isURLSearchParams(params)) {\n serializedParams = params.toString();\n } else {\n var parts = [];\n\n utils.forEach(params, function serialize(val, key) {\n if (val === null || typeof val === 'undefined') {\n return;\n }\n\n if (utils.isArray(val)) {\n key = key + '[]';\n } else {\n val = [val];\n }\n\n utils.forEach(val, function parseValue(v) {\n if (utils.isDate(v)) {\n v = v.toISOString();\n } else if (utils.isObject(v)) {\n v = JSON.stringify(v);\n }\n parts.push(encode(key) + '=' + encode(v));\n });\n });\n\n serializedParams = parts.join('&');\n }\n\n if (serializedParams) {\n var hashmarkIndex = url.indexOf('#');\n if (hashmarkIndex !== -1) {\n url = url.slice(0, hashmarkIndex);\n }\n\n url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams;\n }\n\n return url;\n};\n","'use strict';\n\nvar utils = require('./../utils');\n\nfunction InterceptorManager() {\n this.handlers = [];\n}\n\n/**\n * Add a new interceptor to the stack\n *\n * @param {Function} fulfilled The function to handle `then` for a `Promise`\n * @param {Function} rejected The function to handle `reject` for a `Promise`\n *\n * @return {Number} An ID used to remove interceptor later\n */\nInterceptorManager.prototype.use = function use(fulfilled, rejected) {\n this.handlers.push({\n fulfilled: fulfilled,\n rejected: rejected\n });\n return this.handlers.length - 1;\n};\n\n/**\n * Remove an interceptor from the stack\n *\n * @param {Number} id The ID that was returned by `use`\n */\nInterceptorManager.prototype.eject = function eject(id) {\n if (this.handlers[id]) {\n this.handlers[id] = null;\n }\n};\n\n/**\n * Iterate over all the registered interceptors\n *\n * This method is particularly useful for skipping over any\n * interceptors that may have become `null` calling `eject`.\n *\n * @param {Function} fn The function to call for each interceptor\n */\nInterceptorManager.prototype.forEach = function forEach(fn) {\n utils.forEach(this.handlers, function forEachHandler(h) {\n if (h !== null) {\n fn(h);\n }\n });\n};\n\nmodule.exports = InterceptorManager;\n","'use strict';\n\nvar utils = require('./../utils');\n\n/**\n * Transform the data for a request or a response\n *\n * @param {Object|String} data The data to be transformed\n * @param {Array} headers The headers for the request or response\n * @param {Array|Function} fns A single function or Array of functions\n * @returns {*} The resulting transformed data\n */\nmodule.exports = function transformData(data, headers, fns) {\n /*eslint no-param-reassign:0*/\n utils.forEach(fns, function transform(fn) {\n data = fn(data, headers);\n });\n\n return data;\n};\n","'use strict';\n\nmodule.exports = function isCancel(value) {\n return !!(value && value.__CANCEL__);\n};\n","'use strict';\n\nvar utils = require('../utils');\n\nmodule.exports = function normalizeHeaderName(headers, normalizedName) {\n utils.forEach(headers, function processHeader(value, name) {\n if (name !== normalizedName && name.toUpperCase() === normalizedName.toUpperCase()) {\n headers[normalizedName] = value;\n delete headers[name];\n }\n });\n};\n","'use strict';\n\n/**\n * Update an Error with the specified config, error code, and response.\n *\n * @param {Error} error The error to update.\n * @param {Object} config The config.\n * @param {string} [code] The error code (for example, 'ECONNABORTED').\n * @param {Object} [request] The request.\n * @param {Object} [response] The response.\n * @returns {Error} The error.\n */\nmodule.exports = function enhanceError(error, config, code, request, response) {\n error.config = config;\n if (code) {\n error.code = code;\n }\n\n error.request = request;\n error.response = response;\n error.isAxiosError = true;\n\n error.toJSON = function toJSON() {\n return {\n // Standard\n message: this.message,\n name: this.name,\n // Microsoft\n description: this.description,\n number: this.number,\n // Mozilla\n fileName: this.fileName,\n lineNumber: this.lineNumber,\n columnNumber: this.columnNumber,\n stack: this.stack,\n // Axios\n config: this.config,\n code: this.code\n };\n };\n return error;\n};\n","'use strict';\n\nvar enhanceError = require('./enhanceError');\n\n/**\n * Create an Error with the specified message, config, error code, request and response.\n *\n * @param {string} message The error message.\n * @param {Object} config The config.\n * @param {string} [code] The error code (for example, 'ECONNABORTED').\n * @param {Object} [request] The request.\n * @param {Object} [response] The response.\n * @returns {Error} The created error.\n */\nmodule.exports = function createError(message, config, code, request, response) {\n var error = new Error(message);\n return enhanceError(error, config, code, request, response);\n};\n","'use strict';\n\nvar createError = require('./createError');\n\n/**\n * Resolve or reject a Promise based on response status.\n *\n * @param {Function} resolve A function that resolves the promise.\n * @param {Function} reject A function that rejects the promise.\n * @param {object} response The response.\n */\nmodule.exports = function settle(resolve, reject, response) {\n var validateStatus = response.config.validateStatus;\n if (!response.status || !validateStatus || validateStatus(response.status)) {\n resolve(response);\n } else {\n reject(createError(\n 'Request failed with status code ' + response.status,\n response.config,\n null,\n response.request,\n response\n ));\n }\n};\n","'use strict';\n\nvar utils = require('./../utils');\n\nmodule.exports = (\n utils.isStandardBrowserEnv() ?\n\n // Standard browser envs support document.cookie\n (function standardBrowserEnv() {\n return {\n write: function write(name, value, expires, path, domain, secure) {\n var cookie = [];\n cookie.push(name + '=' + encodeURIComponent(value));\n\n if (utils.isNumber(expires)) {\n cookie.push('expires=' + new Date(expires).toGMTString());\n }\n\n if (utils.isString(path)) {\n cookie.push('path=' + path);\n }\n\n if (utils.isString(domain)) {\n cookie.push('domain=' + domain);\n }\n\n if (secure === true) {\n cookie.push('secure');\n }\n\n document.cookie = cookie.join('; ');\n },\n\n read: function read(name) {\n var match = document.cookie.match(new RegExp('(^|;\\\\s*)(' + name + ')=([^;]*)'));\n return (match ? decodeURIComponent(match[3]) : null);\n },\n\n remove: function remove(name) {\n this.write(name, '', Date.now() - 86400000);\n }\n };\n })() :\n\n // Non standard browser env (web workers, react-native) lack needed support.\n (function nonStandardBrowserEnv() {\n return {\n write: function write() {},\n read: function read() { return null; },\n remove: function remove() {}\n };\n })()\n);\n","'use strict';\n\n/**\n * Determines whether the specified URL is absolute\n *\n * @param {string} url The URL to test\n * @returns {boolean} True if the specified URL is absolute, otherwise false\n */\nmodule.exports = function isAbsoluteURL(url) {\n // A URL is considered absolute if it begins with \"<scheme>://\" or \"//\" (protocol-relative URL).\n // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed\n // by any combination of letters, digits, plus, period, or hyphen.\n return /^([a-z][a-z\\d\\+\\-\\.]*:)?\\/\\//i.test(url);\n};\n","'use strict';\n\n/**\n * Creates a new URL by combining the specified URLs\n *\n * @param {string} baseURL The base URL\n * @param {string} relativeURL The relative URL\n * @returns {string} The combined URL\n */\nmodule.exports = function combineURLs(baseURL, relativeURL) {\n return relativeURL\n ? baseURL.replace(/\\/+$/, '') + '/' + relativeURL.replace(/^\\/+/, '')\n : baseURL;\n};\n","'use strict';\n\nvar isAbsoluteURL = require('../helpers/isAbsoluteURL');\nvar combineURLs = require('../helpers/combineURLs');\n\n/**\n * Creates a new URL by combining the baseURL with the requestedURL,\n * only when the requestedURL is not already an absolute URL.\n * If the requestURL is absolute, this function returns the requestedURL untouched.\n *\n * @param {string} baseURL The base URL\n * @param {string} requestedURL Absolute or relative URL to combine\n * @returns {string} The combined full path\n */\nmodule.exports = function buildFullPath(baseURL, requestedURL) {\n if (baseURL && !isAbsoluteURL(requestedURL)) {\n return combineURLs(baseURL, requestedURL);\n }\n return requestedURL;\n};\n","'use strict';\n\nvar utils = require('./../utils');\n\n// Headers whose duplicates are ignored by node\n// c.f. https://nodejs.org/api/http.html#http_message_headers\nvar ignoreDuplicateOf = [\n 'age', 'authorization', 'content-length', 'content-type', 'etag',\n 'expires', 'from', 'host', 'if-modified-since', 'if-unmodified-since',\n 'last-modified', 'location', 'max-forwards', 'proxy-authorization',\n 'referer', 'retry-after', 'user-agent'\n];\n\n/**\n * Parse headers into an object\n *\n * ```\n * Date: Wed, 27 Aug 2014 08:58:49 GMT\n * Content-Type: application/json\n * Connection: keep-alive\n * Transfer-Encoding: chunked\n * ```\n *\n * @param {String} headers Headers needing to be parsed\n * @returns {Object} Headers parsed into an object\n */\nmodule.exports = function parseHeaders(headers) {\n var parsed = {};\n var key;\n var val;\n var i;\n\n if (!headers) { return parsed; }\n\n utils.forEach(headers.split('\\n'), function parser(line) {\n i = line.indexOf(':');\n key = utils.trim(line.substr(0, i)).toLowerCase();\n val = utils.trim(line.substr(i + 1));\n\n if (key) {\n if (parsed[key] && ignoreDuplicateOf.indexOf(key) >= 0) {\n return;\n }\n if (key === 'set-cookie') {\n parsed[key] = (parsed[key] ? parsed[key] : []).concat([val]);\n } else {\n parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;\n }\n }\n });\n\n return parsed;\n};\n","'use strict';\n\nvar utils = require('./../utils');\n\nmodule.exports = (\n utils.isStandardBrowserEnv() ?\n\n // Standard browser envs have full support of the APIs needed to test\n // whether the request URL is of the same origin as current location.\n (function standardBrowserEnv() {\n var msie = /(msie|trident)/i.test(navigator.userAgent);\n var urlParsingNode = document.createElement('a');\n var originURL;\n\n /**\n * Parse a URL to discover it's components\n *\n * @param {String} url The URL to be parsed\n * @returns {Object}\n */\n function resolveURL(url) {\n var href = url;\n\n if (msie) {\n // IE needs attribute set twice to normalize properties\n urlParsingNode.setAttribute('href', href);\n href = urlParsingNode.href;\n }\n\n urlParsingNode.setAttribute('href', href);\n\n // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils\n return {\n href: urlParsingNode.href,\n protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',\n host: urlParsingNode.host,\n search: urlParsingNode.search ? urlParsingNode.search.replace(/^\\?/, '') : '',\n hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',\n hostname: urlParsingNode.hostname,\n port: urlParsingNode.port,\n pathname: (urlParsingNode.pathname.charAt(0) === '/') ?\n urlParsingNode.pathname :\n '/' + urlParsingNode.pathname\n };\n }\n\n originURL = resolveURL(window.location.href);\n\n /**\n * Determine if a URL shares the same origin as the current location\n *\n * @param {String} requestURL The URL to test\n * @returns {boolean} True if URL shares the same origin, otherwise false\n */\n return function isURLSameOrigin(requestURL) {\n var parsed = (utils.isString(requestURL)) ? resolveURL(requestURL) : requestURL;\n return (parsed.protocol === originURL.protocol &&\n parsed.host === originURL.host);\n };\n })() :\n\n // Non standard browser envs (web workers, react-native) lack needed support.\n (function nonStandardBrowserEnv() {\n return function isURLSameOrigin() {\n return true;\n };\n })()\n);\n","'use strict';\n\nvar utils = require('./../utils');\nvar settle = require('./../core/settle');\nvar cookies = require('./../helpers/cookies');\nvar buildURL = require('./../helpers/buildURL');\nvar buildFullPath = require('../core/buildFullPath');\nvar parseHeaders = require('./../helpers/parseHeaders');\nvar isURLSameOrigin = require('./../helpers/isURLSameOrigin');\nvar createError = require('../core/createError');\n\nmodule.exports = function xhrAdapter(config) {\n return new Promise(function dispatchXhrRequest(resolve, reject) {\n var requestData = config.data;\n var requestHeaders = config.headers;\n\n if (utils.isFormData(requestData)) {\n delete requestHeaders['Content-Type']; // Let the browser set it\n }\n\n var request = new XMLHttpRequest();\n\n // HTTP basic authentication\n if (config.auth) {\n var username = config.auth.username || '';\n var password = config.auth.password ? unescape(encodeURIComponent(config.auth.password)) : '';\n requestHeaders.Authorization = 'Basic ' + btoa(username + ':' + password);\n }\n\n var fullPath = buildFullPath(config.baseURL, config.url);\n request.open(config.method.toUpperCase(), buildURL(fullPath, config.params, config.paramsSerializer), true);\n\n // Set the request timeout in MS\n request.timeout = config.timeout;\n\n // Listen for ready state\n request.onreadystatechange = function handleLoad() {\n if (!request || request.readyState !== 4) {\n return;\n }\n\n // The request errored out and we didn't get a response, this will be\n // handled by onerror instead\n // With one exception: request that using file: protocol, most browsers\n // will return status as 0 even though it's a successful request\n if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) {\n return;\n }\n\n // Prepare the response\n var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null;\n var responseData = !config.responseType || config.responseType === 'text' ? request.responseText : request.response;\n var response = {\n data: responseData,\n status: request.status,\n statusText: request.statusText,\n headers: responseHeaders,\n config: config,\n request: request\n };\n\n settle(resolve, reject, response);\n\n // Clean up request\n request = null;\n };\n\n // Handle browser request cancellation (as opposed to a manual cancellation)\n request.onabort = function handleAbort() {\n if (!request) {\n return;\n }\n\n reject(createError('Request aborted', config, 'ECONNABORTED', request));\n\n // Clean up request\n request = null;\n };\n\n // Handle low level network errors\n request.onerror = function handleError() {\n // Real errors are hidden from us by the browser\n // onerror should only fire if it's a network error\n reject(createError('Network Error', config, null, request));\n\n // Clean up request\n request = null;\n };\n\n // Handle timeout\n request.ontimeout = function handleTimeout() {\n var timeoutErrorMessage = 'timeout of ' + config.timeout + 'ms exceeded';\n if (config.timeoutErrorMessage) {\n timeoutErrorMessage = config.timeoutErrorMessage;\n }\n reject(createError(timeoutErrorMessage, config, 'ECONNABORTED',\n request));\n\n // Clean up request\n request = null;\n };\n\n // Add xsrf header\n // This is only done if running in a standard browser environment.\n // Specifically not if we're in a web worker, or react-native.\n if (utils.isStandardBrowserEnv()) {\n // Add xsrf header\n var xsrfValue = (config.withCredentials || isURLSameOrigin(fullPath)) && config.xsrfCookieName ?\n cookies.read(config.xsrfCookieName) :\n undefined;\n\n if (xsrfValue) {\n requestHeaders[config.xsrfHeaderName] = xsrfValue;\n }\n }\n\n // Add headers to the request\n if ('setRequestHeader' in request) {\n utils.forEach(requestHeaders, function setRequestHeader(val, key) {\n if (typeof requestData === 'undefined' && key.toLowerCase() === 'content-type') {\n // Remove Content-Type if data is undefined\n delete requestHeaders[key];\n } else {\n // Otherwise add header to the request\n request.setRequestHeader(key, val);\n }\n });\n }\n\n // Add withCredentials to request if needed\n if (!utils.isUndefined(config.withCredentials)) {\n request.withCredentials = !!config.withCredentials;\n }\n\n // Add responseType to request if needed\n if (config.responseType) {\n try {\n request.responseType = config.responseType;\n } catch (e) {\n // Expected DOMException thrown by browsers not compatible XMLHttpRequest Level 2.\n // But, this can be suppressed for 'json' type as it can be parsed by default 'transformResponse' function.\n if (config.responseType !== 'json') {\n throw e;\n }\n }\n }\n\n // Handle progress if needed\n if (typeof config.onDownloadProgress === 'function') {\n request.addEventListener('progress', config.onDownloadProgress);\n }\n\n // Not all browsers support upload events\n if (typeof config.onUploadProgress === 'function' && request.upload) {\n request.upload.addEventListener('progress', config.onUploadProgress);\n }\n\n if (config.cancelToken) {\n // Handle cancellation\n config.cancelToken.promise.then(function onCanceled(cancel) {\n if (!request) {\n return;\n }\n\n request.abort();\n reject(cancel);\n // Clean up request\n request = null;\n });\n }\n\n if (!requestData) {\n requestData = null;\n }\n\n // Send the request\n request.send(requestData);\n });\n};\n","'use strict';\n\nvar utils = require('./utils');\nvar normalizeHeaderName = require('./helpers/normalizeHeaderName');\n\nvar DEFAULT_CONTENT_TYPE = {\n 'Content-Type': 'application/x-www-form-urlencoded'\n};\n\nfunction setContentTypeIfUnset(headers, value) {\n if (!utils.isUndefined(headers) && utils.isUndefined(headers['Content-Type'])) {\n headers['Content-Type'] = value;\n }\n}\n\nfunction getDefaultAdapter() {\n var adapter;\n if (typeof XMLHttpRequest !== 'undefined') {\n // For browsers use XHR adapter\n adapter = require('./adapters/xhr');\n } else if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') {\n // For node use HTTP adapter\n adapter = require('./adapters/http');\n }\n return adapter;\n}\n\nvar defaults = {\n adapter: getDefaultAdapter(),\n\n transformRequest: [function transformRequest(data, headers) {\n normalizeHeaderName(headers, 'Accept');\n normalizeHeaderName(headers, 'Content-Type');\n if (utils.isFormData(data) ||\n utils.isArrayBuffer(data) ||\n utils.isBuffer(data) ||\n utils.isStream(data) ||\n utils.isFile(data) ||\n utils.isBlob(data)\n ) {\n return data;\n }\n if (utils.isArrayBufferView(data)) {\n return data.buffer;\n }\n if (utils.isURLSearchParams(data)) {\n setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8');\n return data.toString();\n }\n if (utils.isObject(data)) {\n setContentTypeIfUnset(headers, 'application/json;charset=utf-8');\n return JSON.stringify(data);\n }\n return data;\n }],\n\n transformResponse: [function transformResponse(data) {\n /*eslint no-param-reassign:0*/\n if (typeof data === 'string') {\n try {\n data = JSON.parse(data);\n } catch (e) { /* Ignore */ }\n }\n return data;\n }],\n\n /**\n * A timeout in milliseconds to abort a request. If set to 0 (default) a\n * timeout is not created.\n */\n timeout: 0,\n\n xsrfCookieName: 'XSRF-TOKEN',\n xsrfHeaderName: 'X-XSRF-TOKEN',\n\n maxContentLength: -1,\n maxBodyLength: -1,\n\n validateStatus: function validateStatus(status) {\n return status >= 200 && status < 300;\n }\n};\n\ndefaults.headers = {\n common: {\n 'Accept': 'application/json, text/plain, */*'\n }\n};\n\nutils.forEach(['delete', 'get', 'head'], function forEachMethodNoData(method) {\n defaults.headers[method] = {};\n});\n\nutils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {\n defaults.headers[method] = utils.merge(DEFAULT_CONTENT_TYPE);\n});\n\nmodule.exports = defaults;\n","'use strict';\n\nvar utils = require('./../utils');\nvar transformData = require('./transformData');\nvar isCancel = require('../cancel/isCancel');\nvar defaults = require('../defaults');\n\n/**\n * Throws a `Cancel` if cancellation has been requested.\n */\nfunction throwIfCancellationRequested(config) {\n if (config.cancelToken) {\n config.cancelToken.throwIfRequested();\n }\n}\n\n/**\n * Dispatch a request to the server using the configured adapter.\n *\n * @param {object} config The config that is to be used for the request\n * @returns {Promise} The Promise to be fulfilled\n */\nmodule.exports = function dispatchRequest(config) {\n throwIfCancellationRequested(config);\n\n // Ensure headers exist\n config.headers = config.headers || {};\n\n // Transform request data\n config.data = transformData(\n config.data,\n config.headers,\n config.transformRequest\n );\n\n // Flatten headers\n config.headers = utils.merge(\n config.headers.common || {},\n config.headers[config.method] || {},\n config.headers\n );\n\n utils.forEach(\n ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'],\n function cleanHeaderConfig(method) {\n delete config.headers[method];\n }\n );\n\n var adapter = config.adapter || defaults.adapter;\n\n return adapter(config).then(function onAdapterResolution(response) {\n throwIfCancellationRequested(config);\n\n // Transform response data\n response.data = transformData(\n response.data,\n response.headers,\n config.transformResponse\n );\n\n return response;\n }, function onAdapterRejection(reason) {\n if (!isCancel(reason)) {\n throwIfCancellationRequested(config);\n\n // Transform response data\n if (reason && reason.response) {\n reason.response.data = transformData(\n reason.response.data,\n reason.response.headers,\n config.transformResponse\n );\n }\n }\n\n return Promise.reject(reason);\n });\n};\n","'use strict';\n\nvar utils = require('../utils');\n\n/**\n * Config-specific merge-function which creates a new config-object\n * by merging two configuration objects together.\n *\n * @param {Object} config1\n * @param {Object} config2\n * @returns {Object} New object resulting from merging config2 to config1\n */\nmodule.exports = function mergeConfig(config1, config2) {\n // eslint-disable-next-line no-param-reassign\n config2 = config2 || {};\n var config = {};\n\n var valueFromConfig2Keys = ['url', 'method', 'data'];\n var mergeDeepPropertiesKeys = ['headers', 'auth', 'proxy', 'params'];\n var defaultToConfig2Keys = [\n 'baseURL', 'transformRequest', 'transformResponse', 'paramsSerializer',\n 'timeout', 'timeoutMessage', 'withCredentials', 'adapter', 'responseType', 'xsrfCookieName',\n 'xsrfHeaderName', 'onUploadProgress', 'onDownloadProgress', 'decompress',\n 'maxContentLength', 'maxBodyLength', 'maxRedirects', 'transport', 'httpAgent',\n 'httpsAgent', 'cancelToken', 'socketPath', 'responseEncoding'\n ];\n var directMergeKeys = ['validateStatus'];\n\n function getMergedValue(target, source) {\n if (utils.isPlainObject(target) && utils.isPlainObject(source)) {\n return utils.merge(target, source);\n } else if (utils.isPlainObject(source)) {\n return utils.merge({}, source);\n } else if (utils.isArray(source)) {\n return source.slice();\n }\n return source;\n }\n\n function mergeDeepProperties(prop) {\n if (!utils.isUndefined(config2[prop])) {\n config[prop] = getMergedValue(config1[prop], config2[prop]);\n } else if (!utils.isUndefined(config1[prop])) {\n config[prop] = getMergedValue(undefined, config1[prop]);\n }\n }\n\n utils.forEach(valueFromConfig2Keys, function valueFromConfig2(prop) {\n if (!utils.isUndefined(config2[prop])) {\n config[prop] = getMergedValue(undefined, config2[prop]);\n }\n });\n\n utils.forEach(mergeDeepPropertiesKeys, mergeDeepProperties);\n\n utils.forEach(defaultToConfig2Keys, function defaultToConfig2(prop) {\n if (!utils.isUndefined(config2[prop])) {\n config[prop] = getMergedValue(undefined, config2[prop]);\n } else if (!utils.isUndefined(config1[prop])) {\n config[prop] = getMergedValue(undefined, config1[prop]);\n }\n });\n\n utils.forEach(directMergeKeys, function merge(prop) {\n if (prop in config2) {\n config[prop] = getMergedValue(config1[prop], config2[prop]);\n } else if (prop in config1) {\n config[prop] = getMergedValue(undefined, config1[prop]);\n }\n });\n\n var axiosKeys = valueFromConfig2Keys\n .concat(mergeDeepPropertiesKeys)\n .concat(defaultToConfig2Keys)\n .concat(directMergeKeys);\n\n var otherKeys = Object\n .keys(config1)\n .concat(Object.keys(config2))\n .filter(function filterAxiosKeys(key) {\n return axiosKeys.indexOf(key) === -1;\n });\n\n utils.forEach(otherKeys, mergeDeepProperties);\n\n return config;\n};\n","'use strict';\n\nvar utils = require('./../utils');\nvar buildURL = require('../helpers/buildURL');\nvar InterceptorManager = require('./InterceptorManager');\nvar dispatchRequest = require('./dispatchRequest');\nvar mergeConfig = require('./mergeConfig');\n\n/**\n * Create a new instance of Axios\n *\n * @param {Object} instanceConfig The default config for the instance\n */\nfunction Axios(instanceConfig) {\n this.defaults = instanceConfig;\n this.interceptors = {\n request: new InterceptorManager(),\n response: new InterceptorManager()\n };\n}\n\n/**\n * Dispatch a request\n *\n * @param {Object} config The config specific for this request (merged with this.defaults)\n */\nAxios.prototype.request = function request(config) {\n /*eslint no-param-reassign:0*/\n // Allow for axios('example/url'[, config]) a la fetch API\n if (typeof config === 'string') {\n config = arguments[1] || {};\n config.url = arguments[0];\n } else {\n config = config || {};\n }\n\n config = mergeConfig(this.defaults, config);\n\n // Set config.method\n if (config.method) {\n config.method = config.method.toLowerCase();\n } else if (this.defaults.method) {\n config.method = this.defaults.method.toLowerCase();\n } else {\n config.method = 'get';\n }\n\n // Hook up interceptors middleware\n var chain = [dispatchRequest, undefined];\n var promise = Promise.resolve(config);\n\n this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {\n chain.unshift(interceptor.fulfilled, interceptor.rejected);\n });\n\n this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {\n chain.push(interceptor.fulfilled, interceptor.rejected);\n });\n\n while (chain.length) {\n promise = promise.then(chain.shift(), chain.shift());\n }\n\n return promise;\n};\n\nAxios.prototype.getUri = function getUri(config) {\n config = mergeConfig(this.defaults, config);\n return buildURL(config.url, config.params, config.paramsSerializer).replace(/^\\?/, '');\n};\n\n// Provide aliases for supported request methods\nutils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {\n /*eslint func-names:0*/\n Axios.prototype[method] = function(url, config) {\n return this.request(mergeConfig(config || {}, {\n method: method,\n url: url,\n data: (config || {}).data\n }));\n };\n});\n\nutils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {\n /*eslint func-names:0*/\n Axios.prototype[method] = function(url, data, config) {\n return this.request(mergeConfig(config || {}, {\n method: method,\n url: url,\n data: data\n }));\n };\n});\n\nmodule.exports = Axios;\n","'use strict';\n\n/**\n * A `Cancel` is an object that is thrown when an operation is canceled.\n *\n * @class\n * @param {string=} message The message.\n */\nfunction Cancel(message) {\n this.message = message;\n}\n\nCancel.prototype.toString = function toString() {\n return 'Cancel' + (this.message ? ': ' + this.message : '');\n};\n\nCancel.prototype.__CANCEL__ = true;\n\nmodule.exports = Cancel;\n","'use strict';\n\nvar Cancel = require('./Cancel');\n\n/**\n * A `CancelToken` is an object that can be used to request cancellation of an operation.\n *\n * @class\n * @param {Function} executor The executor function.\n */\nfunction CancelToken(executor) {\n if (typeof executor !== 'function') {\n throw new TypeError('executor must be a function.');\n }\n\n var resolvePromise;\n this.promise = new Promise(function promiseExecutor(resolve) {\n resolvePromise = resolve;\n });\n\n var token = this;\n executor(function cancel(message) {\n if (token.reason) {\n // Cancellation has already been requested\n return;\n }\n\n token.reason = new Cancel(message);\n resolvePromise(token.reason);\n });\n}\n\n/**\n * Throws a `Cancel` if cancellation has been requested.\n */\nCancelToken.prototype.throwIfRequested = function throwIfRequested() {\n if (this.reason) {\n throw this.reason;\n }\n};\n\n/**\n * Returns an object that contains a new `CancelToken` and a function that, when called,\n * cancels the `CancelToken`.\n */\nCancelToken.source = function source() {\n var cancel;\n var token = new CancelToken(function executor(c) {\n cancel = c;\n });\n return {\n token: token,\n cancel: cancel\n };\n};\n\nmodule.exports = CancelToken;\n","'use strict';\n\n/**\n * Syntactic sugar for invoking a function and expanding an array for arguments.\n *\n * Common use case would be to use `Function.prototype.apply`.\n *\n * ```js\n * function f(x, y, z) {}\n * var args = [1, 2, 3];\n * f.apply(null, args);\n * ```\n *\n * With `spread` this example can be re-written.\n *\n * ```js\n * spread(function(x, y, z) {})([1, 2, 3]);\n * ```\n *\n * @param {Function} callback\n * @returns {Function}\n */\nmodule.exports = function spread(callback) {\n return function wrap(arr) {\n return callback.apply(null, arr);\n };\n};\n","'use strict';\n\n/**\n * Determines whether the payload is an error thrown by Axios\n *\n * @param {*} payload The value to test\n * @returns {boolean} True if the payload is an error thrown by Axios, otherwise false\n */\nmodule.exports = function isAxiosError(payload) {\n return (typeof payload === 'object') && (payload.isAxiosError === true);\n};\n","'use strict';\n\nvar utils = require('./utils');\nvar bind = require('./helpers/bind');\nvar Axios = require('./core/Axios');\nvar mergeConfig = require('./core/mergeConfig');\nvar defaults = require('./defaults');\n\n/**\n * Create an instance of Axios\n *\n * @param {Object} defaultConfig The default config for the instance\n * @return {Axios} A new instance of Axios\n */\nfunction createInstance(defaultConfig) {\n var context = new Axios(defaultConfig);\n var instance = bind(Axios.prototype.request, context);\n\n // Copy axios.prototype to instance\n utils.extend(instance, Axios.prototype, context);\n\n // Copy context to instance\n utils.extend(instance, context);\n\n return instance;\n}\n\n// Create the default instance to be exported\nvar axios = createInstance(defaults);\n\n// Expose Axios class to allow class inheritance\naxios.Axios = Axios;\n\n// Factory for creating new instances\naxios.create = function create(instanceConfig) {\n return createInstance(mergeConfig(axios.defaults, instanceConfig));\n};\n\n// Expose Cancel & CancelToken\naxios.Cancel = require('./cancel/Cancel');\naxios.CancelToken = require('./cancel/CancelToken');\naxios.isCancel = require('./cancel/isCancel');\n\n// Expose all/spread\naxios.all = function all(promises) {\n return Promise.all(promises);\n};\naxios.spread = require('./helpers/spread');\n\n// Expose isAxiosError\naxios.isAxiosError = require('./helpers/isAxiosError');\n\nmodule.exports = axios;\n\n// Allow use of default import syntax in TypeScript\nmodule.exports.default = axios;\n","module.exports = require('./lib/axios');","\nimport { setLogger } from '../ulity/debug';\nimport * as debug from '../ulity/debug';\nimport Event from '../ulity/event';\nimport Events from '../base/event';\nimport axios from 'axios';\nimport * as Base from '../base/export';\n\nexport default class RTCEndpoint extends Event\n{\n constructor(options)\n {\n super('RTCPusherPlayer');\n this.TAG = '[RTCPusherPlayer]';\n\n let defaults = {\n element: '',// html video element\n debug: false,// if output debug log\n zlmsdpUrl:'',\n simulcast:false,\n useCamera:true,\n audioEnable:true,\n videoEnable:true,\n recvOnly:false,\n resolution:{w:0,h:0},\n usedatachannel:false,\n };\n \n this.options = Object.assign({}, defaults, options);\n\n if(this.options.debug)\n {\n setLogger();\n }\n\n this.e = {\n onicecandidate:this._onIceCandidate.bind(this),\n ontrack:this._onTrack.bind(this),\n onicecandidateerror:this._onIceCandidateError.bind(this),\n onconnectionstatechange:this._onconnectionstatechange.bind(this),\n ondatachannelopen:this._onDataChannelOpen.bind(this),\n ondatachannelmsg:this._onDataChannelMsg.bind(this),\n ondatachannelerr:this._onDataChannelErr.bind(this),\n ondatachannelclose:this._onDataChannelClose.bind(this),\n };\n\n this._remoteStream = null;\n this._localStream = null;\n\n this.pc = new RTCPeerConnection(null);\n\n this.pc.onicecandidate = this.e.onicecandidate;\n this.pc.onicecandidateerror = this.e.onicecandidateerror;\n this.pc.ontrack = this.e.ontrack;\n this.pc.onconnectionstatechange = this.e.onconnectionstatechange;\n\n this.datachannel = null;\n if(this.options.usedatachannel){\n this.datachannel = this.pc.createDataChannel('chat');\n this.datachannel.onclose = this.e.ondatachannelclose;\n this.datachannel.onerror = this.e.ondatachannelerr;\n this.datachannel.onmessage = this.e.ondatachannelmsg;\n this.datachannel.onopen = this.e.ondatachannelopen;\n }\n\n if(!this.options.recvOnly && (this.options.audioEnable || this.options.videoEnable))\n this.start();\n else\n this.receive();\n \n }\n\n receive()\n {\n let audioTransceiver = null;\n let videoTransceiver = null;\n\n //debug.error(this.TAG,'this not implement');\n const AudioTransceiverInit = {\n direction: 'recvonly',\n sendEncodings:[]\n };\n const VideoTransceiverInit= {\n direction: 'recvonly',\n sendEncodings:[],\n };\n\n audioTransceiver = this.pc.addTransceiver('audio',AudioTransceiverInit);\n videoTransceiver = this.pc.addTransceiver('video',VideoTransceiverInit);\n \n this.pc.createOffer().then((desc)=>{\n debug.log(this.TAG,'offer:',desc.sdp);\n this.pc.setLocalDescription(desc).then(() => {\n axios({\n method: 'post',\n url:this.options.zlmsdpUrl,\n responseType:'json',\n data:desc.sdp,\n headers:{\n 'Content-Type':'text/plain;charset=utf-8'\n }\n }).then(response=>{\n let ret = response.data;//JSON.parse(response.data);\n if(ret.code != 0)\n {// mean failed for offer/anwser exchange \n this.dispatch(Events.WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED,ret);\n return;\n }\n let anwser = {};\n anwser.sdp = ret.sdp;\n anwser.type = 'answer';\n debug.log(this.TAG,'answer:',ret.sdp);\n\n this.pc.setRemoteDescription(anwser).then(()=>{\n debug.log(this.TAG,'set remote sucess');\n }).catch(e=>{\n debug.error(this.TAG,e);\n });\n });\n });\n }).catch(e=>{\n debug.error(this.TAG,e);\n });\n }\n\n start()\n {\n let videoConstraints = false;\n let audioConstraints = false;\n\n if(this.options.useCamera)\n {\n if(this.options.videoEnable)\n videoConstraints = new Base.VideoTrackConstraints(Base.VideoSourceInfo.CAMERA);\n if(this.options.audioEnable)\n audioConstraints = new Base.AudioTrackConstraints(Base.AudioSourceInfo.MIC);\n }\n else\n {\n if(this.options.videoEnable)\n {\n videoConstraints = new Base.VideoTrackConstraints(Base.VideoSourceInfo.SCREENCAST);\n if(this.options.audioEnable)\n audioConstraints = new Base.AudioTrackConstraints(Base.AudioSourceInfo.SCREENCAST);\n }\n else\n {\n if(this.options.audioEnable)\n audioConstraints = new Base.AudioTrackConstraints(Base.AudioSourceInfo.MIC);\n else\n {// error shared display media not only audio\n debug.error(this.TAG,'error paramter');\n }\n }\n \n }\n\n if(this.options.resolution.w !=0 && this.options.resolution.h!=0 && typeof videoConstraints == 'object'){\n videoConstraints.resolution = new Base.Resolution(this.options.resolution.w ,this.options.resolution.h);\n }\n\n Base.MediaStreamFactory.createMediaStream(new Base.StreamConstraints(\n audioConstraints, videoConstraints)).then(stream => {\n\n this._localStream = stream;\n\n this.dispatch(Events.WEBRTC_ON_LOCAL_STREAM,stream);\n\n const AudioTransceiverInit = {\n direction: 'sendrecv',\n sendEncodings:[]\n };\n const VideoTransceiverInit= {\n direction: 'sendrecv',\n sendEncodings:[],\n };\n \n if(this.options.simulcast && stream.getVideoTracks().length>0)\n {\n VideoTransceiverInit.sendEncodings = [\n { rid: 'h', active: true, maxBitrate: 1000000 },\n { rid: 'm', active: true, maxBitrate: 500000, scaleResolutionDownBy: 2 },\n { rid: 'l', active: true, maxBitrate: 200000, scaleResolutionDownBy: 4 }\n ];\n }\n let audioTransceiver = null;\n let videoTransceiver = null;\n if (this.options.audioEnable) {\n if (stream.getAudioTracks().length > 0) {\n audioTransceiver = this.pc.addTransceiver(stream.getAudioTracks()[0],\n AudioTransceiverInit);\n }\n else {\n AudioTransceiverInit.direction = 'recvonly';\n audioTransceiver = this.pc.addTransceiver('audio', AudioTransceiverInit);\n }\n }\n \n if (this.options.videoEnable) {\n if (stream.getVideoTracks().length > 0) {\n videoTransceiver = this.pc.addTransceiver(stream.getVideoTracks()[0],\n VideoTransceiverInit);\n }\n else {\n VideoTransceiverInit.direction = 'recvonly';\n videoTransceiver = this.pc.addTransceiver('video',\n VideoTransceiverInit);\n }\n }\n\n /*\n stream.getTracks().forEach((track,idx)=>{\n debug.log(this.TAG,track);\n this.pc.addTrack(track);\n });\n */\n this.pc.createOffer().then((desc)=>{\n debug.log(this.TAG,'offer:',desc.sdp);\n this.pc.setLocalDescription(desc).then(() => {\n axios({\n method: 'post',\n url:this.options.zlmsdpUrl,\n responseType:'json',\n data:desc.sdp,\n headers:{\n 'Content-Type':'text/plain;charset=utf-8'\n }\n }).then(response=>{\n let ret = response.data;//JSON.parse(response.data);\n if(ret.code != 0)\n {// mean failed for offer/anwser exchange \n this.dispatch(Events.WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED,ret);\n return;\n }\n let anwser = {};\n anwser.sdp = ret.sdp;\n anwser.type = 'answer';\n debug.log(this.TAG,'answer:',ret.sdp);\n \n this.pc.setRemoteDescription(anwser).then(()=>{\n debug.log(this.TAG,'set remote sucess');\n }).catch(e=>{\n debug.error(this.TAG,e);\n });\n });\n });\n }).catch(e=>{\n debug.error(this.TAG,e);\n });\n\n }).catch(e=>{\n this.dispatch(Events.CAPTURE_STREAM_FAILED);\n //debug.error(this.TAG,e);\n });\n \n //const offerOptions = {};\n /*\n if (typeof this.pc.addTransceiver === 'function') {\n // |direction| seems not working on Safari.\n this.pc.addTransceiver('audio', { direction: 'recvonly' });\n this.pc.addTransceiver('video', { direction: 'recvonly' });\n } else {\n offerOptions.offerToReceiveAudio = true;\n offerOptions.offerToReceiveVideo = true;\n }\n */\n\n\n\n }\n _onIceCandidate(event) {\n if (event.candidate) { \n debug.log('Remote ICE candidate: \\n ' + event.candidate.candidate);\n // Send the candidate to the remote peer\n }\n else {\n // All ICE candidates have been sent\n }\n }\n\n _onTrack(event){\n if(this.options.element && event.streams && event.streams.length>0)\n {\n this.options.element.srcObject = event.streams[0];\n this._remoteStream = event.streams[0];\n\n this.dispatch(Events.WEBRTC_ON_REMOTE_STREAMS,event);\n }\n else\n {\n debug.error('element pararm is failed');\n }\n }\n\n _onIceCandidateError(event){\n this.dispatch(Events.WEBRTC_ICE_CANDIDATE_ERROR,event);\n }\n\n _onconnectionstatechange(event) {\n this.dispatch(Events.WEBRTC_ON_CONNECTION_STATE_CHANGE, this.pc.connectionState);\n }\n\n _onDataChannelOpen(event) {\n debug.log(this.TAG,'ondatachannel open:',event);\n this.dispatch(Events.WEBRTC_ON_DATA_CHANNEL_OPEN,event);\n }\n _onDataChannelMsg(event) {\n debug.log(this.TAG,'ondatachannel msg:',event);\n this.dispatch(Events.WEBRTC_ON_DATA_CHANNEL_MSG,event);\n }\n _onDataChannelErr(event){\n debug.log(this.TAG,'ondatachannel err:',event);\n this.dispatch(Events.WEBRTC_ON_DATA_CHANNEL_ERR,event);\n }\n _onDataChannelClose(event){\n debug.log(this.TAG,'ondatachannel close:',event);\n this.dispatch(Events.WEBRTC_ON_DATA_CHANNEL_CLOSE,event);\n }\n sendMsg(data){\n if(this.datachannel !=null){\n this.datachannel.send(data);\n }else{\n debug.error(this.TAG,'data channel is null');\n }\n }\n closeDataChannel(){\n if(this.datachannel){\n this.datachannel.close();\n this.datachannel = null;\n }\n }\n close()\n { \n this.closeDataChannel();\n if(this.pc)\n {\n this.pc.close();\n this.pc=null;\n }\n\n if(this.options)\n {\n this.options=null;\n }\n\n if(this._localStream)\n {\n this._localStream.getTracks().forEach((track,idx)=>{\n track.stop();\n });\n }\n\n if(this._remoteStream)\n {\n this._remoteStream.getTracks().forEach((track,idx)=>{\n track.stop();\n });\n }\n }\n\n get remoteStream()\n {\n return this._remoteStream;\n }\n \n get localStream()\n {\n return this._localStream;\n }\n}\n","import * as mediaformat from './mediaformat';\nimport * as MediaFactory from './mediastream-factory';\n\n\nconst quickScan=[\n {\n 'label': '4K(UHD)',\n 'width': 3840,\n 'height': 2160\n },\n {\n 'label': '1080p(FHD)',\n 'width': 1920,\n 'height': 1080\n },\n {\n 'label': 'UXGA',\n 'width': 1600,\n 'height': 1200,\n 'ratio': '4:3'\n },\n {\n 'label': '720p(HD)',\n 'width': 1280,\n 'height': 720\n },\n {\n 'label': 'SVGA',\n 'width': 800,\n 'height': 600\n },\n {\n 'label': 'VGA',\n 'width': 640,\n 'height': 480\n },\n {\n 'label': '360p(nHD)',\n 'width': 640,\n 'height': 360\n },\n {\n 'label': 'CIF',\n 'width': 352,\n 'height': 288\n },\n {\n 'label': 'QVGA',\n 'width': 320,\n 'height': 240\n },\n {\n 'label': 'QCIF',\n 'width': 176,\n 'height': 144\n },\n {\n 'label': 'QQVGA',\n 'width': 160,\n 'height': 120\n }\n];\n\n\n\n\nexport default function GetSupportCameraResolutions(){\n return new Promise(function (resolve, reject) {\n let resolutions = [];\n let ok = 0;\n let err = 0;\n for (let i = 0; i < quickScan.length; ++i) {\n let videoConstraints = new MediaFactory.VideoTrackConstraints(mediaformat.VideoSourceInfo.CAMERA);\n videoConstraints.resolution = new mediaformat.Resolution(quickScan[i].width, quickScan[i].height);\n\n MediaFactory.MediaStreamFactory.createMediaStream(new MediaFactory.StreamConstraints(\n false, videoConstraints)).then(stream => {\n resolutions.push(quickScan[i]);\n ok++;\n if(ok+err == quickScan.length)\n {\n resolve(resolutions);\n }\n }).catch(e => {\n err++;\n if(ok+err == quickScan.length)\n {\n resolve(resolutions);\n }\n });\n }\n });\n}\n\nexport function GetAllScanResolution()\n{\n return quickScan;\n}\nexport function isSupportResolution(w,h)\n{\n return new Promise(function (resolve, reject) {\n let videoConstraints = new MediaFactory.VideoTrackConstraints(mediaformat.VideoSourceInfo.CAMERA);\n videoConstraints.resolution = new mediaformat.Resolution(w,h);\n\n MediaFactory.MediaStreamFactory.createMediaStream(new MediaFactory.StreamConstraints(\n false, videoConstraints)).then(stream => {\n resolve();\n }).catch(e => {\n reject(e);\n });\n });\n}","import * as events from './base/event';\nimport * as compile from './ulity/version';\nimport * as media from './base/export';\nimport * as endpoint from './endpoint/endpoint';\nimport * as resolution from './base/resolutionfind';\n\n\n\nconsole.log('build date:',compile.BUILD_DATE);\nconsole.log('version:',compile.VERSION);\n\nexport const Events = events.default;\nexport const Media = media;\nexport const Endpoint = endpoint.default;\nexport const GetSupportCameraResolutions = resolution.default;\nexport const GetAllScanResolution = resolution.GetAllScanResolution;\nexport const isSupportResolution = resolution.isSupportResolution;"],"names":["Events","WEBRTC_NOT_SUPPORT","WEBRTC_ICE_CANDIDATE_ERROR","WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED","WEBRTC_ON_REMOTE_STREAMS","WEBRTC_ON_LOCAL_STREAM","WEBRTC_ON_CONNECTION_STATE_CHANGE","WEBRTC_ON_DATA_CHANNEL_OPEN","WEBRTC_ON_DATA_CHANNEL_CLOSE","WEBRTC_ON_DATA_CHANNEL_ERR","WEBRTC_ON_DATA_CHANNEL_MSG","CAPTURE_STREAM_FAILED","VERSION","BUILD_DATE","isFirefox","window","navigator","userAgent","match","isChrome","isEdge","AudioSourceInfo","MIC","SCREENCAST","FILE","MIXED","VideoSourceInfo","CAMERA","TrackKind","AUDIO","VIDEO","AUDIO_AND_VIDEO","Resolution","constructor","width","height","log","isObject","utils.log","shimGetUserMedia","shimGetDisplayMedia","shimOnTrack","utils.wrapPeerConnectionEvent","utils.filterStats","shimPeerConnection","filterIceServers","utils.deprecated","sdp","SDPUtils","shimRTCPeerConnection","utils.compactObject","utils.detectBrowser","utils.extractVersion","utils.disableLog","utils.disableWarnings","chromeShim.shimPeerConnection","commonShim.shimAddIceCandidateNullOrEmpty","chromeShim.shimGetUserMedia","chromeShim.shimMediaStream","chromeShim.shimOnTrack","chromeShim.shimAddTrackRemoveTrack","chromeShim.shimGetSendersWithDtmf","chromeShim.shimGetStats","chromeShim.shimSenderReceiverGetStats","chromeShim.fixNegotiationNeeded","commonShim.shimRTCIceCandidate","commonShim.shimConnectionState","commonShim.shimMaxMessageSize","commonShim.shimSendThrowTypeError","commonShim.removeExtmapAllowMixed","firefoxShim.shimPeerConnection","firefoxShim.shimGetUserMedia","firefoxShim.shimOnTrack","firefoxShim.shimRemoveStream","firefoxShim.shimSenderGetStats","firefoxShim.shimReceiverGetStats","firefoxShim.shimRTCDataChannel","firefoxShim.shimAddTransceiver","firefoxShim.shimGetParameters","firefoxShim.shimCreateOffer","firefoxShim.shimCreateAnswer","edgeShim.shimPeerConnection","edgeShim.shimGetUserMedia","edgeShim.shimGetDisplayMedia","edgeShim.shimReplaceTrack","safariShim.shimRTCIceServerUrls","safariShim.shimCreateOfferLegacy","safariShim.shimCallbacksAPI","safariShim.shimLocalStreamsAPI","safariShim.shimRemoteStreamsAPI","safariShim.shimTrackEventTransceiver","safariShim.shimGetUserMedia","safariShim.shimAudioContext","AudioTrackConstraints","source","Object","values","MediaFormatModule","some","v","TypeError","deviceId","undefined","VideoTrackConstraints","resolution","frameRate","StreamConstraints","audioConstraints","videoConstraints","audio","video","isVideoConstrainsForScreenCast","constraints","MediaStreamFactory","createMediaStream","Promise","reject","utils","mediaConstraints","create","exact","mediaSource","mediaDevices","getDisplayMedia","getUserMedia","logger","errorLogger","setLogger","console","error","message","optionalParams","Event","type","listener","on","event","fn","push","off","index","indexOf","splice","offAll","dispatch","data","map","each","apply","require$$0","require$$1","defaults","InterceptorManager","Cancel","Axios","axios","require$$2","require$$3","require$$4","RTCEndpoint","options","TAG","element","debug","zlmsdpUrl","simulcast","useCamera","audioEnable","videoEnable","recvOnly","w","h","usedatachannel","assign","e","onicecandidate","_onIceCandidate","bind","ontrack","_onTrack","onicecandidateerror","_onIceCandidateError","onconnectionstatechange","_onconnectionstatechange","ondatachannelopen","_onDataChannelOpen","ondatachannelmsg","_onDataChannelMsg","ondatachannelerr","_onDataChannelErr","ondatachannelclose","_onDataChannelClose","_remoteStream","_localStream","pc","RTCPeerConnection","datachannel","createDataChannel","onclose","onerror","onmessage","onopen","start","receive","AudioTransceiverInit","direction","sendEncodings","VideoTransceiverInit","audioTransceiver","addTransceiver","videoTransceiver","createOffer","then","desc","setLocalDescription","method","url","responseType","headers","response","ret","code","anwser","setRemoteDescription","catch","Base","stream","getVideoTracks","length","rid","active","maxBitrate","scaleResolutionDownBy","getAudioTracks","candidate","streams","srcObject","connectionState","sendMsg","send","closeDataChannel","close","getTracks","forEach","track","idx","stop","remoteStream","localStream","quickScan","GetSupportCameraResolutions","resolve","resolutions","ok","err","i","MediaFactory","mediaformat","GetAllScanResolution","isSupportResolution","compile","events","Media","media","Endpoint","endpoint"],"mappings":"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"} | |
| 2 | 1 | \ No newline at end of file |
| 2 | +{"version":3,"file":"ZLMRTCClient.js","sources":["../src/base/event.js","../src/ulity/version.js","../src/base/utils.js","../src/base/mediaformat.js","../node_modules/webrtc-adapter/src/js/utils.js","../node_modules/webrtc-adapter/src/js/chrome/getusermedia.js","../node_modules/webrtc-adapter/src/js/chrome/getdisplaymedia.js","../node_modules/webrtc-adapter/src/js/chrome/chrome_shim.js","../node_modules/webrtc-adapter/src/js/edge/filtericeservers.js","../node_modules/sdp/sdp.js","../node_modules/rtcpeerconnection-shim/rtcpeerconnection.js","../node_modules/webrtc-adapter/src/js/edge/getusermedia.js","../node_modules/webrtc-adapter/src/js/edge/getdisplaymedia.js","../node_modules/webrtc-adapter/src/js/edge/edge_shim.js","../node_modules/webrtc-adapter/src/js/firefox/getusermedia.js","../node_modules/webrtc-adapter/src/js/firefox/getdisplaymedia.js","../node_modules/webrtc-adapter/src/js/firefox/firefox_shim.js","../node_modules/webrtc-adapter/src/js/safari/safari_shim.js","../node_modules/webrtc-adapter/src/js/common_shim.js","../node_modules/webrtc-adapter/src/js/adapter_factory.js","../node_modules/webrtc-adapter/src/js/adapter_core.js","../src/base/mediastream-factory.js","../src/base/export.js","../src/ulity/debug.js","../src/ulity/event.js","../node_modules/axios/lib/helpers/bind.js","../node_modules/axios/lib/utils.js","../node_modules/axios/lib/helpers/buildURL.js","../node_modules/axios/lib/core/InterceptorManager.js","../node_modules/axios/lib/helpers/normalizeHeaderName.js","../node_modules/axios/lib/core/AxiosError.js","../node_modules/axios/lib/defaults/transitional.js","../node_modules/axios/lib/helpers/toFormData.js","../node_modules/axios/lib/core/settle.js","../node_modules/axios/lib/helpers/cookies.js","../node_modules/axios/lib/helpers/isAbsoluteURL.js","../node_modules/axios/lib/helpers/combineURLs.js","../node_modules/axios/lib/core/buildFullPath.js","../node_modules/axios/lib/helpers/parseHeaders.js","../node_modules/axios/lib/helpers/isURLSameOrigin.js","../node_modules/axios/lib/cancel/CanceledError.js","../node_modules/axios/lib/helpers/parseProtocol.js","../node_modules/axios/lib/adapters/xhr.js","../node_modules/axios/lib/helpers/null.js","../node_modules/axios/lib/defaults/index.js","../node_modules/axios/lib/core/transformData.js","../node_modules/axios/lib/cancel/isCancel.js","../node_modules/axios/lib/core/dispatchRequest.js","../node_modules/axios/lib/core/mergeConfig.js","../node_modules/axios/lib/env/data.js","../node_modules/axios/lib/helpers/validator.js","../node_modules/axios/lib/core/Axios.js","../node_modules/axios/lib/cancel/CancelToken.js","../node_modules/axios/lib/helpers/spread.js","../node_modules/axios/lib/helpers/isAxiosError.js","../node_modules/axios/lib/axios.js","../node_modules/axios/index.js","../src/endpoint/endpoint.js","../src/base/resolutionfind.js","../src/export.js"],"sourcesContent":["const Events = {\n\tWEBRTC_NOT_SUPPORT : 'WEBRTC_NOT_SUPPORT',\n\tWEBRTC_ICE_CANDIDATE_ERROR : 'WEBRTC_ICE_CANDIDATE_ERROR',\n\tWEBRTC_OFFER_ANWSER_EXCHANGE_FAILED:'WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED',\n\tWEBRTC_ON_REMOTE_STREAMS:'WEBRTC_ON_REMOTE_STREAMS',\n\tWEBRTC_ON_LOCAL_STREAM:'WEBRTC_ON_LOCAL_STREAM',\n\tWEBRTC_ON_CONNECTION_STATE_CHANGE:'WEBRTC_ON_CONNECTION_STATE_CHANGE',\n\tWEBRTC_ON_DATA_CHANNEL_OPEN:'WEBRTC_ON_DATA_CHANNEL_OPEN',\n\tWEBRTC_ON_DATA_CHANNEL_CLOSE:'WEBRTC_ON_DATA_CHANNEL_CLOSE',\n\tWEBRTC_ON_DATA_CHANNEL_ERR:'WEBRTC_ON_DATA_CHANNEL_ERR',\n\tWEBRTC_ON_DATA_CHANNEL_MSG:'WEBRTC_ON_DATA_CHANNEL_MSG',\n\tCAPTURE_STREAM_FAILED:'CAPTURE_STREAM_FAILED',\n};\n\nexport default Events;","export const VERSION = '__VERSION__';\nexport const BUILD_DATE = '__BUILD_DATE__';","// Copyright (C) <2018> Intel Corporation\n//\n// SPDX-License-Identifier: Apache-2.0\n\n\n// eslint-disable-next-line require-jsdoc\nexport function isFirefox() {\n return window.navigator.userAgent.match('Firefox') !== null;\n}\n// eslint-disable-next-line require-jsdoc\nexport function isChrome() {\n return window.navigator.userAgent.match('Chrome') !== null;\n}\n// eslint-disable-next-line require-jsdoc\nexport function isSafari() {\n return /^((?!chrome|android).)*safari/i.test(window.navigator.userAgent);\n}\n// eslint-disable-next-line require-jsdoc\nexport function isEdge() {\n return window.navigator.userAgent.match(/Edge\\/(\\d+).(\\d+)$/) !== null;\n}\n// eslint-disable-next-line require-jsdoc\nexport function createUuid() {\n return 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n const r = Math.random() * 16 | 0;\n const v = c === 'x' ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n}","// Copyright (C) <2018> Intel Corporation\n//\n// SPDX-License-Identifier: Apache-2.0\n\n'use strict';\n/**\n * @class AudioSourceInfo\n * @classDesc Source info about an audio track. Values: 'mic', 'screen-cast', 'file', 'mixed'.\n * @memberOf Owt.Base\n * @readonly\n * @enum {string}\n */\nexport const AudioSourceInfo = {\n MIC: 'mic',\n SCREENCAST: 'screen-cast',\n FILE: 'file',\n MIXED: 'mixed',\n};\n\n/**\n * @class VideoSourceInfo\n * @classDesc Source info about a video track. Values: 'camera', 'screen-cast', 'file', 'mixed'.\n * @memberOf Owt.Base\n * @readonly\n * @enum {string}\n */\nexport const VideoSourceInfo = {\n CAMERA: 'camera',\n SCREENCAST: 'screen-cast',\n FILE: 'file',\n MIXED: 'mixed',\n};\n\n/**\n * @class TrackKind\n * @classDesc Kind of a track. Values: 'audio' for audio track, 'video' for video track, 'av' for both audio and video tracks.\n * @memberOf Owt.Base\n * @readonly\n * @enum {string}\n */\nexport const TrackKind = {\n /**\n * Audio tracks.\n * @type string\n */\n AUDIO: 'audio',\n /**\n * Video tracks.\n * @type string\n */\n VIDEO: 'video',\n /**\n * Both audio and video tracks.\n * @type string\n */\n AUDIO_AND_VIDEO: 'av',\n};\n/**\n * @class Resolution\n * @memberOf Owt.Base\n * @classDesc The Resolution defines the size of a rectangle.\n * @constructor\n * @param {number} width\n * @param {number} height\n */\nexport class Resolution {\n // eslint-disable-next-line require-jsdoc\n constructor(width, height) {\n /**\n * @member {number} width\n * @instance\n * @memberof Owt.Base.Resolution\n */\n this.width = width;\n /**\n * @member {number} height\n * @instance\n * @memberof Owt.Base.Resolution\n */\n this.height = height;\n }\n}\n","/*\n * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n /* eslint-env node */\n'use strict';\n\nlet logDisabled_ = true;\nlet deprecationWarnings_ = true;\n\n/**\n * Extract browser version out of the provided user agent string.\n *\n * @param {!string} uastring userAgent string.\n * @param {!string} expr Regular expression used as match criteria.\n * @param {!number} pos position in the version string to be returned.\n * @return {!number} browser version.\n */\nexport function extractVersion(uastring, expr, pos) {\n const match = uastring.match(expr);\n return match && match.length >= pos && parseInt(match[pos], 10);\n}\n\n// Wraps the peerconnection event eventNameToWrap in a function\n// which returns the modified event object (or false to prevent\n// the event).\nexport function wrapPeerConnectionEvent(window, eventNameToWrap, wrapper) {\n if (!window.RTCPeerConnection) {\n return;\n }\n const proto = window.RTCPeerConnection.prototype;\n const nativeAddEventListener = proto.addEventListener;\n proto.addEventListener = function(nativeEventName, cb) {\n if (nativeEventName !== eventNameToWrap) {\n return nativeAddEventListener.apply(this, arguments);\n }\n const wrappedCallback = (e) => {\n const modifiedEvent = wrapper(e);\n if (modifiedEvent) {\n if (cb.handleEvent) {\n cb.handleEvent(modifiedEvent);\n } else {\n cb(modifiedEvent);\n }\n }\n };\n this._eventMap = this._eventMap || {};\n if (!this._eventMap[eventNameToWrap]) {\n this._eventMap[eventNameToWrap] = new Map();\n }\n this._eventMap[eventNameToWrap].set(cb, wrappedCallback);\n return nativeAddEventListener.apply(this, [nativeEventName,\n wrappedCallback]);\n };\n\n const nativeRemoveEventListener = proto.removeEventListener;\n proto.removeEventListener = function(nativeEventName, cb) {\n if (nativeEventName !== eventNameToWrap || !this._eventMap\n || !this._eventMap[eventNameToWrap]) {\n return nativeRemoveEventListener.apply(this, arguments);\n }\n if (!this._eventMap[eventNameToWrap].has(cb)) {\n return nativeRemoveEventListener.apply(this, arguments);\n }\n const unwrappedCb = this._eventMap[eventNameToWrap].get(cb);\n this._eventMap[eventNameToWrap].delete(cb);\n if (this._eventMap[eventNameToWrap].size === 0) {\n delete this._eventMap[eventNameToWrap];\n }\n if (Object.keys(this._eventMap).length === 0) {\n delete this._eventMap;\n }\n return nativeRemoveEventListener.apply(this, [nativeEventName,\n unwrappedCb]);\n };\n\n Object.defineProperty(proto, 'on' + eventNameToWrap, {\n get() {\n return this['_on' + eventNameToWrap];\n },\n set(cb) {\n if (this['_on' + eventNameToWrap]) {\n this.removeEventListener(eventNameToWrap,\n this['_on' + eventNameToWrap]);\n delete this['_on' + eventNameToWrap];\n }\n if (cb) {\n this.addEventListener(eventNameToWrap,\n this['_on' + eventNameToWrap] = cb);\n }\n },\n enumerable: true,\n configurable: true\n });\n}\n\nexport function disableLog(bool) {\n if (typeof bool !== 'boolean') {\n return new Error('Argument type: ' + typeof bool +\n '. Please use a boolean.');\n }\n logDisabled_ = bool;\n return (bool) ? 'adapter.js logging disabled' :\n 'adapter.js logging enabled';\n}\n\n/**\n * Disable or enable deprecation warnings\n * @param {!boolean} bool set to true to disable warnings.\n */\nexport function disableWarnings(bool) {\n if (typeof bool !== 'boolean') {\n return new Error('Argument type: ' + typeof bool +\n '. Please use a boolean.');\n }\n deprecationWarnings_ = !bool;\n return 'adapter.js deprecation warnings ' + (bool ? 'disabled' : 'enabled');\n}\n\nexport function log() {\n if (typeof window === 'object') {\n if (logDisabled_) {\n return;\n }\n if (typeof console !== 'undefined' && typeof console.log === 'function') {\n console.log.apply(console, arguments);\n }\n }\n}\n\n/**\n * Shows a deprecation warning suggesting the modern and spec-compatible API.\n */\nexport function deprecated(oldMethod, newMethod) {\n if (!deprecationWarnings_) {\n return;\n }\n console.warn(oldMethod + ' is deprecated, please use ' + newMethod +\n ' instead.');\n}\n\n/**\n * Browser detector.\n *\n * @return {object} result containing browser and version\n * properties.\n */\nexport function detectBrowser(window) {\n // Returned result object.\n const result = {browser: null, version: null};\n\n // Fail early if it's not a browser\n if (typeof window === 'undefined' || !window.navigator) {\n result.browser = 'Not a browser.';\n return result;\n }\n\n const {navigator} = window;\n\n if (navigator.mozGetUserMedia) { // Firefox.\n result.browser = 'firefox';\n result.version = extractVersion(navigator.userAgent,\n /Firefox\\/(\\d+)\\./, 1);\n } else if (navigator.webkitGetUserMedia ||\n (window.isSecureContext === false && window.webkitRTCPeerConnection &&\n !window.RTCIceGatherer)) {\n // Chrome, Chromium, Webview, Opera.\n // Version matches Chrome/WebRTC version.\n // Chrome 74 removed webkitGetUserMedia on http as well so we need the\n // more complicated fallback to webkitRTCPeerConnection.\n result.browser = 'chrome';\n result.version = extractVersion(navigator.userAgent,\n /Chrom(e|ium)\\/(\\d+)\\./, 2);\n } else if (navigator.mediaDevices &&\n navigator.userAgent.match(/Edge\\/(\\d+).(\\d+)$/)) { // Edge.\n result.browser = 'edge';\n result.version = extractVersion(navigator.userAgent,\n /Edge\\/(\\d+).(\\d+)$/, 2);\n } else if (window.RTCPeerConnection &&\n navigator.userAgent.match(/AppleWebKit\\/(\\d+)\\./)) { // Safari.\n result.browser = 'safari';\n result.version = extractVersion(navigator.userAgent,\n /AppleWebKit\\/(\\d+)\\./, 1);\n result.supportsUnifiedPlan = window.RTCRtpTransceiver &&\n 'currentDirection' in window.RTCRtpTransceiver.prototype;\n } else { // Default fallthrough: not supported.\n result.browser = 'Not a supported browser.';\n return result;\n }\n\n return result;\n}\n\n/**\n * Checks if something is an object.\n *\n * @param {*} val The something you want to check.\n * @return true if val is an object, false otherwise.\n */\nfunction isObject(val) {\n return Object.prototype.toString.call(val) === '[object Object]';\n}\n\n/**\n * Remove all empty objects and undefined values\n * from a nested object -- an enhanced and vanilla version\n * of Lodash's `compact`.\n */\nexport function compactObject(data) {\n if (!isObject(data)) {\n return data;\n }\n\n return Object.keys(data).reduce(function(accumulator, key) {\n const isObj = isObject(data[key]);\n const value = isObj ? compactObject(data[key]) : data[key];\n const isEmptyObject = isObj && !Object.keys(value).length;\n if (value === undefined || isEmptyObject) {\n return accumulator;\n }\n return Object.assign(accumulator, {[key]: value});\n }, {});\n}\n\n/* iterates the stats graph recursively. */\nexport function walkStats(stats, base, resultSet) {\n if (!base || resultSet.has(base.id)) {\n return;\n }\n resultSet.set(base.id, base);\n Object.keys(base).forEach(name => {\n if (name.endsWith('Id')) {\n walkStats(stats, stats.get(base[name]), resultSet);\n } else if (name.endsWith('Ids')) {\n base[name].forEach(id => {\n walkStats(stats, stats.get(id), resultSet);\n });\n }\n });\n}\n\n/* filter getStats for a sender/receiver track. */\nexport function filterStats(result, track, outbound) {\n const streamStatsType = outbound ? 'outbound-rtp' : 'inbound-rtp';\n const filteredResult = new Map();\n if (track === null) {\n return filteredResult;\n }\n const trackStats = [];\n result.forEach(value => {\n if (value.type === 'track' &&\n value.trackIdentifier === track.id) {\n trackStats.push(value);\n }\n });\n trackStats.forEach(trackStat => {\n result.forEach(stats => {\n if (stats.type === streamStatsType && stats.trackId === trackStat.id) {\n walkStats(result, stats, filteredResult);\n }\n });\n });\n return filteredResult;\n}\n\n","/*\n * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n/* eslint-env node */\n'use strict';\nimport * as utils from '../utils.js';\nconst logging = utils.log;\n\nexport function shimGetUserMedia(window, browserDetails) {\n const navigator = window && window.navigator;\n\n if (!navigator.mediaDevices) {\n return;\n }\n\n const constraintsToChrome_ = function(c) {\n if (typeof c !== 'object' || c.mandatory || c.optional) {\n return c;\n }\n const cc = {};\n Object.keys(c).forEach(key => {\n if (key === 'require' || key === 'advanced' || key === 'mediaSource') {\n return;\n }\n const r = (typeof c[key] === 'object') ? c[key] : {ideal: c[key]};\n if (r.exact !== undefined && typeof r.exact === 'number') {\n r.min = r.max = r.exact;\n }\n const oldname_ = function(prefix, name) {\n if (prefix) {\n return prefix + name.charAt(0).toUpperCase() + name.slice(1);\n }\n return (name === 'deviceId') ? 'sourceId' : name;\n };\n if (r.ideal !== undefined) {\n cc.optional = cc.optional || [];\n let oc = {};\n if (typeof r.ideal === 'number') {\n oc[oldname_('min', key)] = r.ideal;\n cc.optional.push(oc);\n oc = {};\n oc[oldname_('max', key)] = r.ideal;\n cc.optional.push(oc);\n } else {\n oc[oldname_('', key)] = r.ideal;\n cc.optional.push(oc);\n }\n }\n if (r.exact !== undefined && typeof r.exact !== 'number') {\n cc.mandatory = cc.mandatory || {};\n cc.mandatory[oldname_('', key)] = r.exact;\n } else {\n ['min', 'max'].forEach(mix => {\n if (r[mix] !== undefined) {\n cc.mandatory = cc.mandatory || {};\n cc.mandatory[oldname_(mix, key)] = r[mix];\n }\n });\n }\n });\n if (c.advanced) {\n cc.optional = (cc.optional || []).concat(c.advanced);\n }\n return cc;\n };\n\n const shimConstraints_ = function(constraints, func) {\n if (browserDetails.version >= 61) {\n return func(constraints);\n }\n constraints = JSON.parse(JSON.stringify(constraints));\n if (constraints && typeof constraints.audio === 'object') {\n const remap = function(obj, a, b) {\n if (a in obj && !(b in obj)) {\n obj[b] = obj[a];\n delete obj[a];\n }\n };\n constraints = JSON.parse(JSON.stringify(constraints));\n remap(constraints.audio, 'autoGainControl', 'googAutoGainControl');\n remap(constraints.audio, 'noiseSuppression', 'googNoiseSuppression');\n constraints.audio = constraintsToChrome_(constraints.audio);\n }\n if (constraints && typeof constraints.video === 'object') {\n // Shim facingMode for mobile & surface pro.\n let face = constraints.video.facingMode;\n face = face && ((typeof face === 'object') ? face : {ideal: face});\n const getSupportedFacingModeLies = browserDetails.version < 66;\n\n if ((face && (face.exact === 'user' || face.exact === 'environment' ||\n face.ideal === 'user' || face.ideal === 'environment')) &&\n !(navigator.mediaDevices.getSupportedConstraints &&\n navigator.mediaDevices.getSupportedConstraints().facingMode &&\n !getSupportedFacingModeLies)) {\n delete constraints.video.facingMode;\n let matches;\n if (face.exact === 'environment' || face.ideal === 'environment') {\n matches = ['back', 'rear'];\n } else if (face.exact === 'user' || face.ideal === 'user') {\n matches = ['front'];\n }\n if (matches) {\n // Look for matches in label, or use last cam for back (typical).\n return navigator.mediaDevices.enumerateDevices()\n .then(devices => {\n devices = devices.filter(d => d.kind === 'videoinput');\n let dev = devices.find(d => matches.some(match =>\n d.label.toLowerCase().includes(match)));\n if (!dev && devices.length && matches.includes('back')) {\n dev = devices[devices.length - 1]; // more likely the back cam\n }\n if (dev) {\n constraints.video.deviceId = face.exact ? {exact: dev.deviceId} :\n {ideal: dev.deviceId};\n }\n constraints.video = constraintsToChrome_(constraints.video);\n logging('chrome: ' + JSON.stringify(constraints));\n return func(constraints);\n });\n }\n }\n constraints.video = constraintsToChrome_(constraints.video);\n }\n logging('chrome: ' + JSON.stringify(constraints));\n return func(constraints);\n };\n\n const shimError_ = function(e) {\n if (browserDetails.version >= 64) {\n return e;\n }\n return {\n name: {\n PermissionDeniedError: 'NotAllowedError',\n PermissionDismissedError: 'NotAllowedError',\n InvalidStateError: 'NotAllowedError',\n DevicesNotFoundError: 'NotFoundError',\n ConstraintNotSatisfiedError: 'OverconstrainedError',\n TrackStartError: 'NotReadableError',\n MediaDeviceFailedDueToShutdown: 'NotAllowedError',\n MediaDeviceKillSwitchOn: 'NotAllowedError',\n TabCaptureError: 'AbortError',\n ScreenCaptureError: 'AbortError',\n DeviceCaptureError: 'AbortError'\n }[e.name] || e.name,\n message: e.message,\n constraint: e.constraint || e.constraintName,\n toString() {\n return this.name + (this.message && ': ') + this.message;\n }\n };\n };\n\n const getUserMedia_ = function(constraints, onSuccess, onError) {\n shimConstraints_(constraints, c => {\n navigator.webkitGetUserMedia(c, onSuccess, e => {\n if (onError) {\n onError(shimError_(e));\n }\n });\n });\n };\n navigator.getUserMedia = getUserMedia_.bind(navigator);\n\n // Even though Chrome 45 has navigator.mediaDevices and a getUserMedia\n // function which returns a Promise, it does not accept spec-style\n // constraints.\n if (navigator.mediaDevices.getUserMedia) {\n const origGetUserMedia = navigator.mediaDevices.getUserMedia.\n bind(navigator.mediaDevices);\n navigator.mediaDevices.getUserMedia = function(cs) {\n return shimConstraints_(cs, c => origGetUserMedia(c).then(stream => {\n if (c.audio && !stream.getAudioTracks().length ||\n c.video && !stream.getVideoTracks().length) {\n stream.getTracks().forEach(track => {\n track.stop();\n });\n throw new DOMException('', 'NotFoundError');\n }\n return stream;\n }, e => Promise.reject(shimError_(e))));\n };\n }\n}\n","/*\n * Copyright (c) 2018 The adapter.js project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n/* eslint-env node */\n'use strict';\nexport function shimGetDisplayMedia(window, getSourceId) {\n if (window.navigator.mediaDevices &&\n 'getDisplayMedia' in window.navigator.mediaDevices) {\n return;\n }\n if (!(window.navigator.mediaDevices)) {\n return;\n }\n // getSourceId is a function that returns a promise resolving with\n // the sourceId of the screen/window/tab to be shared.\n if (typeof getSourceId !== 'function') {\n console.error('shimGetDisplayMedia: getSourceId argument is not ' +\n 'a function');\n return;\n }\n window.navigator.mediaDevices.getDisplayMedia =\n function getDisplayMedia(constraints) {\n return getSourceId(constraints)\n .then(sourceId => {\n const widthSpecified = constraints.video && constraints.video.width;\n const heightSpecified = constraints.video &&\n constraints.video.height;\n const frameRateSpecified = constraints.video &&\n constraints.video.frameRate;\n constraints.video = {\n mandatory: {\n chromeMediaSource: 'desktop',\n chromeMediaSourceId: sourceId,\n maxFrameRate: frameRateSpecified || 3\n }\n };\n if (widthSpecified) {\n constraints.video.mandatory.maxWidth = widthSpecified;\n }\n if (heightSpecified) {\n constraints.video.mandatory.maxHeight = heightSpecified;\n }\n return window.navigator.mediaDevices.getUserMedia(constraints);\n });\n };\n}\n","/*\n * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n /* eslint-env node */\n'use strict';\nimport * as utils from '../utils.js';\n\nexport {shimGetUserMedia} from './getusermedia';\nexport {shimGetDisplayMedia} from './getdisplaymedia';\n\nexport function shimMediaStream(window) {\n window.MediaStream = window.MediaStream || window.webkitMediaStream;\n}\n\nexport function shimOnTrack(window) {\n if (typeof window === 'object' && window.RTCPeerConnection && !('ontrack' in\n window.RTCPeerConnection.prototype)) {\n Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', {\n get() {\n return this._ontrack;\n },\n set(f) {\n if (this._ontrack) {\n this.removeEventListener('track', this._ontrack);\n }\n this.addEventListener('track', this._ontrack = f);\n },\n enumerable: true,\n configurable: true\n });\n const origSetRemoteDescription =\n window.RTCPeerConnection.prototype.setRemoteDescription;\n window.RTCPeerConnection.prototype.setRemoteDescription =\n function setRemoteDescription() {\n if (!this._ontrackpoly) {\n this._ontrackpoly = (e) => {\n // onaddstream does not fire when a track is added to an existing\n // stream. But stream.onaddtrack is implemented so we use that.\n e.stream.addEventListener('addtrack', te => {\n let receiver;\n if (window.RTCPeerConnection.prototype.getReceivers) {\n receiver = this.getReceivers()\n .find(r => r.track && r.track.id === te.track.id);\n } else {\n receiver = {track: te.track};\n }\n\n const event = new Event('track');\n event.track = te.track;\n event.receiver = receiver;\n event.transceiver = {receiver};\n event.streams = [e.stream];\n this.dispatchEvent(event);\n });\n e.stream.getTracks().forEach(track => {\n let receiver;\n if (window.RTCPeerConnection.prototype.getReceivers) {\n receiver = this.getReceivers()\n .find(r => r.track && r.track.id === track.id);\n } else {\n receiver = {track};\n }\n const event = new Event('track');\n event.track = track;\n event.receiver = receiver;\n event.transceiver = {receiver};\n event.streams = [e.stream];\n this.dispatchEvent(event);\n });\n };\n this.addEventListener('addstream', this._ontrackpoly);\n }\n return origSetRemoteDescription.apply(this, arguments);\n };\n } else {\n // even if RTCRtpTransceiver is in window, it is only used and\n // emitted in unified-plan. Unfortunately this means we need\n // to unconditionally wrap the event.\n utils.wrapPeerConnectionEvent(window, 'track', e => {\n if (!e.transceiver) {\n Object.defineProperty(e, 'transceiver',\n {value: {receiver: e.receiver}});\n }\n return e;\n });\n }\n}\n\nexport function shimGetSendersWithDtmf(window) {\n // Overrides addTrack/removeTrack, depends on shimAddTrackRemoveTrack.\n if (typeof window === 'object' && window.RTCPeerConnection &&\n !('getSenders' in window.RTCPeerConnection.prototype) &&\n 'createDTMFSender' in window.RTCPeerConnection.prototype) {\n const shimSenderWithDtmf = function(pc, track) {\n return {\n track,\n get dtmf() {\n if (this._dtmf === undefined) {\n if (track.kind === 'audio') {\n this._dtmf = pc.createDTMFSender(track);\n } else {\n this._dtmf = null;\n }\n }\n return this._dtmf;\n },\n _pc: pc\n };\n };\n\n // augment addTrack when getSenders is not available.\n if (!window.RTCPeerConnection.prototype.getSenders) {\n window.RTCPeerConnection.prototype.getSenders = function getSenders() {\n this._senders = this._senders || [];\n return this._senders.slice(); // return a copy of the internal state.\n };\n const origAddTrack = window.RTCPeerConnection.prototype.addTrack;\n window.RTCPeerConnection.prototype.addTrack =\n function addTrack(track, stream) {\n let sender = origAddTrack.apply(this, arguments);\n if (!sender) {\n sender = shimSenderWithDtmf(this, track);\n this._senders.push(sender);\n }\n return sender;\n };\n\n const origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack;\n window.RTCPeerConnection.prototype.removeTrack =\n function removeTrack(sender) {\n origRemoveTrack.apply(this, arguments);\n const idx = this._senders.indexOf(sender);\n if (idx !== -1) {\n this._senders.splice(idx, 1);\n }\n };\n }\n const origAddStream = window.RTCPeerConnection.prototype.addStream;\n window.RTCPeerConnection.prototype.addStream = function addStream(stream) {\n this._senders = this._senders || [];\n origAddStream.apply(this, [stream]);\n stream.getTracks().forEach(track => {\n this._senders.push(shimSenderWithDtmf(this, track));\n });\n };\n\n const origRemoveStream = window.RTCPeerConnection.prototype.removeStream;\n window.RTCPeerConnection.prototype.removeStream =\n function removeStream(stream) {\n this._senders = this._senders || [];\n origRemoveStream.apply(this, [stream]);\n\n stream.getTracks().forEach(track => {\n const sender = this._senders.find(s => s.track === track);\n if (sender) { // remove sender\n this._senders.splice(this._senders.indexOf(sender), 1);\n }\n });\n };\n } else if (typeof window === 'object' && window.RTCPeerConnection &&\n 'getSenders' in window.RTCPeerConnection.prototype &&\n 'createDTMFSender' in window.RTCPeerConnection.prototype &&\n window.RTCRtpSender &&\n !('dtmf' in window.RTCRtpSender.prototype)) {\n const origGetSenders = window.RTCPeerConnection.prototype.getSenders;\n window.RTCPeerConnection.prototype.getSenders = function getSenders() {\n const senders = origGetSenders.apply(this, []);\n senders.forEach(sender => sender._pc = this);\n return senders;\n };\n\n Object.defineProperty(window.RTCRtpSender.prototype, 'dtmf', {\n get() {\n if (this._dtmf === undefined) {\n if (this.track.kind === 'audio') {\n this._dtmf = this._pc.createDTMFSender(this.track);\n } else {\n this._dtmf = null;\n }\n }\n return this._dtmf;\n }\n });\n }\n}\n\nexport function shimGetStats(window) {\n if (!window.RTCPeerConnection) {\n return;\n }\n\n const origGetStats = window.RTCPeerConnection.prototype.getStats;\n window.RTCPeerConnection.prototype.getStats = function getStats() {\n const [selector, onSucc, onErr] = arguments;\n\n // If selector is a function then we are in the old style stats so just\n // pass back the original getStats format to avoid breaking old users.\n if (arguments.length > 0 && typeof selector === 'function') {\n return origGetStats.apply(this, arguments);\n }\n\n // When spec-style getStats is supported, return those when called with\n // either no arguments or the selector argument is null.\n if (origGetStats.length === 0 && (arguments.length === 0 ||\n typeof selector !== 'function')) {\n return origGetStats.apply(this, []);\n }\n\n const fixChromeStats_ = function(response) {\n const standardReport = {};\n const reports = response.result();\n reports.forEach(report => {\n const standardStats = {\n id: report.id,\n timestamp: report.timestamp,\n type: {\n localcandidate: 'local-candidate',\n remotecandidate: 'remote-candidate'\n }[report.type] || report.type\n };\n report.names().forEach(name => {\n standardStats[name] = report.stat(name);\n });\n standardReport[standardStats.id] = standardStats;\n });\n\n return standardReport;\n };\n\n // shim getStats with maplike support\n const makeMapStats = function(stats) {\n return new Map(Object.keys(stats).map(key => [key, stats[key]]));\n };\n\n if (arguments.length >= 2) {\n const successCallbackWrapper_ = function(response) {\n onSucc(makeMapStats(fixChromeStats_(response)));\n };\n\n return origGetStats.apply(this, [successCallbackWrapper_,\n selector]);\n }\n\n // promise-support\n return new Promise((resolve, reject) => {\n origGetStats.apply(this, [\n function(response) {\n resolve(makeMapStats(fixChromeStats_(response)));\n }, reject]);\n }).then(onSucc, onErr);\n };\n}\n\nexport function shimSenderReceiverGetStats(window) {\n if (!(typeof window === 'object' && window.RTCPeerConnection &&\n window.RTCRtpSender && window.RTCRtpReceiver)) {\n return;\n }\n\n // shim sender stats.\n if (!('getStats' in window.RTCRtpSender.prototype)) {\n const origGetSenders = window.RTCPeerConnection.prototype.getSenders;\n if (origGetSenders) {\n window.RTCPeerConnection.prototype.getSenders = function getSenders() {\n const senders = origGetSenders.apply(this, []);\n senders.forEach(sender => sender._pc = this);\n return senders;\n };\n }\n\n const origAddTrack = window.RTCPeerConnection.prototype.addTrack;\n if (origAddTrack) {\n window.RTCPeerConnection.prototype.addTrack = function addTrack() {\n const sender = origAddTrack.apply(this, arguments);\n sender._pc = this;\n return sender;\n };\n }\n window.RTCRtpSender.prototype.getStats = function getStats() {\n const sender = this;\n return this._pc.getStats().then(result =>\n /* Note: this will include stats of all senders that\n * send a track with the same id as sender.track as\n * it is not possible to identify the RTCRtpSender.\n */\n utils.filterStats(result, sender.track, true));\n };\n }\n\n // shim receiver stats.\n if (!('getStats' in window.RTCRtpReceiver.prototype)) {\n const origGetReceivers = window.RTCPeerConnection.prototype.getReceivers;\n if (origGetReceivers) {\n window.RTCPeerConnection.prototype.getReceivers =\n function getReceivers() {\n const receivers = origGetReceivers.apply(this, []);\n receivers.forEach(receiver => receiver._pc = this);\n return receivers;\n };\n }\n utils.wrapPeerConnectionEvent(window, 'track', e => {\n e.receiver._pc = e.srcElement;\n return e;\n });\n window.RTCRtpReceiver.prototype.getStats = function getStats() {\n const receiver = this;\n return this._pc.getStats().then(result =>\n utils.filterStats(result, receiver.track, false));\n };\n }\n\n if (!('getStats' in window.RTCRtpSender.prototype &&\n 'getStats' in window.RTCRtpReceiver.prototype)) {\n return;\n }\n\n // shim RTCPeerConnection.getStats(track).\n const origGetStats = window.RTCPeerConnection.prototype.getStats;\n window.RTCPeerConnection.prototype.getStats = function getStats() {\n if (arguments.length > 0 &&\n arguments[0] instanceof window.MediaStreamTrack) {\n const track = arguments[0];\n let sender;\n let receiver;\n let err;\n this.getSenders().forEach(s => {\n if (s.track === track) {\n if (sender) {\n err = true;\n } else {\n sender = s;\n }\n }\n });\n this.getReceivers().forEach(r => {\n if (r.track === track) {\n if (receiver) {\n err = true;\n } else {\n receiver = r;\n }\n }\n return r.track === track;\n });\n if (err || (sender && receiver)) {\n return Promise.reject(new DOMException(\n 'There are more than one sender or receiver for the track.',\n 'InvalidAccessError'));\n } else if (sender) {\n return sender.getStats();\n } else if (receiver) {\n return receiver.getStats();\n }\n return Promise.reject(new DOMException(\n 'There is no sender or receiver for the track.',\n 'InvalidAccessError'));\n }\n return origGetStats.apply(this, arguments);\n };\n}\n\nexport function shimAddTrackRemoveTrackWithNative(window) {\n // shim addTrack/removeTrack with native variants in order to make\n // the interactions with legacy getLocalStreams behave as in other browsers.\n // Keeps a mapping stream.id => [stream, rtpsenders...]\n window.RTCPeerConnection.prototype.getLocalStreams =\n function getLocalStreams() {\n this._shimmedLocalStreams = this._shimmedLocalStreams || {};\n return Object.keys(this._shimmedLocalStreams)\n .map(streamId => this._shimmedLocalStreams[streamId][0]);\n };\n\n const origAddTrack = window.RTCPeerConnection.prototype.addTrack;\n window.RTCPeerConnection.prototype.addTrack =\n function addTrack(track, stream) {\n if (!stream) {\n return origAddTrack.apply(this, arguments);\n }\n this._shimmedLocalStreams = this._shimmedLocalStreams || {};\n\n const sender = origAddTrack.apply(this, arguments);\n if (!this._shimmedLocalStreams[stream.id]) {\n this._shimmedLocalStreams[stream.id] = [stream, sender];\n } else if (this._shimmedLocalStreams[stream.id].indexOf(sender) === -1) {\n this._shimmedLocalStreams[stream.id].push(sender);\n }\n return sender;\n };\n\n const origAddStream = window.RTCPeerConnection.prototype.addStream;\n window.RTCPeerConnection.prototype.addStream = function addStream(stream) {\n this._shimmedLocalStreams = this._shimmedLocalStreams || {};\n\n stream.getTracks().forEach(track => {\n const alreadyExists = this.getSenders().find(s => s.track === track);\n if (alreadyExists) {\n throw new DOMException('Track already exists.',\n 'InvalidAccessError');\n }\n });\n const existingSenders = this.getSenders();\n origAddStream.apply(this, arguments);\n const newSenders = this.getSenders()\n .filter(newSender => existingSenders.indexOf(newSender) === -1);\n this._shimmedLocalStreams[stream.id] = [stream].concat(newSenders);\n };\n\n const origRemoveStream = window.RTCPeerConnection.prototype.removeStream;\n window.RTCPeerConnection.prototype.removeStream =\n function removeStream(stream) {\n this._shimmedLocalStreams = this._shimmedLocalStreams || {};\n delete this._shimmedLocalStreams[stream.id];\n return origRemoveStream.apply(this, arguments);\n };\n\n const origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack;\n window.RTCPeerConnection.prototype.removeTrack =\n function removeTrack(sender) {\n this._shimmedLocalStreams = this._shimmedLocalStreams || {};\n if (sender) {\n Object.keys(this._shimmedLocalStreams).forEach(streamId => {\n const idx = this._shimmedLocalStreams[streamId].indexOf(sender);\n if (idx !== -1) {\n this._shimmedLocalStreams[streamId].splice(idx, 1);\n }\n if (this._shimmedLocalStreams[streamId].length === 1) {\n delete this._shimmedLocalStreams[streamId];\n }\n });\n }\n return origRemoveTrack.apply(this, arguments);\n };\n}\n\nexport function shimAddTrackRemoveTrack(window, browserDetails) {\n if (!window.RTCPeerConnection) {\n return;\n }\n // shim addTrack and removeTrack.\n if (window.RTCPeerConnection.prototype.addTrack &&\n browserDetails.version >= 65) {\n return shimAddTrackRemoveTrackWithNative(window);\n }\n\n // also shim pc.getLocalStreams when addTrack is shimmed\n // to return the original streams.\n const origGetLocalStreams = window.RTCPeerConnection.prototype\n .getLocalStreams;\n window.RTCPeerConnection.prototype.getLocalStreams =\n function getLocalStreams() {\n const nativeStreams = origGetLocalStreams.apply(this);\n this._reverseStreams = this._reverseStreams || {};\n return nativeStreams.map(stream => this._reverseStreams[stream.id]);\n };\n\n const origAddStream = window.RTCPeerConnection.prototype.addStream;\n window.RTCPeerConnection.prototype.addStream = function addStream(stream) {\n this._streams = this._streams || {};\n this._reverseStreams = this._reverseStreams || {};\n\n stream.getTracks().forEach(track => {\n const alreadyExists = this.getSenders().find(s => s.track === track);\n if (alreadyExists) {\n throw new DOMException('Track already exists.',\n 'InvalidAccessError');\n }\n });\n // Add identity mapping for consistency with addTrack.\n // Unless this is being used with a stream from addTrack.\n if (!this._reverseStreams[stream.id]) {\n const newStream = new window.MediaStream(stream.getTracks());\n this._streams[stream.id] = newStream;\n this._reverseStreams[newStream.id] = stream;\n stream = newStream;\n }\n origAddStream.apply(this, [stream]);\n };\n\n const origRemoveStream = window.RTCPeerConnection.prototype.removeStream;\n window.RTCPeerConnection.prototype.removeStream =\n function removeStream(stream) {\n this._streams = this._streams || {};\n this._reverseStreams = this._reverseStreams || {};\n\n origRemoveStream.apply(this, [(this._streams[stream.id] || stream)]);\n delete this._reverseStreams[(this._streams[stream.id] ?\n this._streams[stream.id].id : stream.id)];\n delete this._streams[stream.id];\n };\n\n window.RTCPeerConnection.prototype.addTrack =\n function addTrack(track, stream) {\n if (this.signalingState === 'closed') {\n throw new DOMException(\n 'The RTCPeerConnection\\'s signalingState is \\'closed\\'.',\n 'InvalidStateError');\n }\n const streams = [].slice.call(arguments, 1);\n if (streams.length !== 1 ||\n !streams[0].getTracks().find(t => t === track)) {\n // this is not fully correct but all we can manage without\n // [[associated MediaStreams]] internal slot.\n throw new DOMException(\n 'The adapter.js addTrack polyfill only supports a single ' +\n ' stream which is associated with the specified track.',\n 'NotSupportedError');\n }\n\n const alreadyExists = this.getSenders().find(s => s.track === track);\n if (alreadyExists) {\n throw new DOMException('Track already exists.',\n 'InvalidAccessError');\n }\n\n this._streams = this._streams || {};\n this._reverseStreams = this._reverseStreams || {};\n const oldStream = this._streams[stream.id];\n if (oldStream) {\n // this is using odd Chrome behaviour, use with caution:\n // https://bugs.chromium.org/p/webrtc/issues/detail?id=7815\n // Note: we rely on the high-level addTrack/dtmf shim to\n // create the sender with a dtmf sender.\n oldStream.addTrack(track);\n\n // Trigger ONN async.\n Promise.resolve().then(() => {\n this.dispatchEvent(new Event('negotiationneeded'));\n });\n } else {\n const newStream = new window.MediaStream([track]);\n this._streams[stream.id] = newStream;\n this._reverseStreams[newStream.id] = stream;\n this.addStream(newStream);\n }\n return this.getSenders().find(s => s.track === track);\n };\n\n // replace the internal stream id with the external one and\n // vice versa.\n function replaceInternalStreamId(pc, description) {\n let sdp = description.sdp;\n Object.keys(pc._reverseStreams || []).forEach(internalId => {\n const externalStream = pc._reverseStreams[internalId];\n const internalStream = pc._streams[externalStream.id];\n sdp = sdp.replace(new RegExp(internalStream.id, 'g'),\n externalStream.id);\n });\n return new RTCSessionDescription({\n type: description.type,\n sdp\n });\n }\n function replaceExternalStreamId(pc, description) {\n let sdp = description.sdp;\n Object.keys(pc._reverseStreams || []).forEach(internalId => {\n const externalStream = pc._reverseStreams[internalId];\n const internalStream = pc._streams[externalStream.id];\n sdp = sdp.replace(new RegExp(externalStream.id, 'g'),\n internalStream.id);\n });\n return new RTCSessionDescription({\n type: description.type,\n sdp\n });\n }\n ['createOffer', 'createAnswer'].forEach(function(method) {\n const nativeMethod = window.RTCPeerConnection.prototype[method];\n const methodObj = {[method]() {\n const args = arguments;\n const isLegacyCall = arguments.length &&\n typeof arguments[0] === 'function';\n if (isLegacyCall) {\n return nativeMethod.apply(this, [\n (description) => {\n const desc = replaceInternalStreamId(this, description);\n args[0].apply(null, [desc]);\n },\n (err) => {\n if (args[1]) {\n args[1].apply(null, err);\n }\n }, arguments[2]\n ]);\n }\n return nativeMethod.apply(this, arguments)\n .then(description => replaceInternalStreamId(this, description));\n }};\n window.RTCPeerConnection.prototype[method] = methodObj[method];\n });\n\n const origSetLocalDescription =\n window.RTCPeerConnection.prototype.setLocalDescription;\n window.RTCPeerConnection.prototype.setLocalDescription =\n function setLocalDescription() {\n if (!arguments.length || !arguments[0].type) {\n return origSetLocalDescription.apply(this, arguments);\n }\n arguments[0] = replaceExternalStreamId(this, arguments[0]);\n return origSetLocalDescription.apply(this, arguments);\n };\n\n // TODO: mangle getStats: https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamstats-streamidentifier\n\n const origLocalDescription = Object.getOwnPropertyDescriptor(\n window.RTCPeerConnection.prototype, 'localDescription');\n Object.defineProperty(window.RTCPeerConnection.prototype,\n 'localDescription', {\n get() {\n const description = origLocalDescription.get.apply(this);\n if (description.type === '') {\n return description;\n }\n return replaceInternalStreamId(this, description);\n }\n });\n\n window.RTCPeerConnection.prototype.removeTrack =\n function removeTrack(sender) {\n if (this.signalingState === 'closed') {\n throw new DOMException(\n 'The RTCPeerConnection\\'s signalingState is \\'closed\\'.',\n 'InvalidStateError');\n }\n // We can not yet check for sender instanceof RTCRtpSender\n // since we shim RTPSender. So we check if sender._pc is set.\n if (!sender._pc) {\n throw new DOMException('Argument 1 of RTCPeerConnection.removeTrack ' +\n 'does not implement interface RTCRtpSender.', 'TypeError');\n }\n const isLocal = sender._pc === this;\n if (!isLocal) {\n throw new DOMException('Sender was not created by this connection.',\n 'InvalidAccessError');\n }\n\n // Search for the native stream the senders track belongs to.\n this._streams = this._streams || {};\n let stream;\n Object.keys(this._streams).forEach(streamid => {\n const hasTrack = this._streams[streamid].getTracks()\n .find(track => sender.track === track);\n if (hasTrack) {\n stream = this._streams[streamid];\n }\n });\n\n if (stream) {\n if (stream.getTracks().length === 1) {\n // if this is the last track of the stream, remove the stream. This\n // takes care of any shimmed _senders.\n this.removeStream(this._reverseStreams[stream.id]);\n } else {\n // relying on the same odd chrome behaviour as above.\n stream.removeTrack(sender.track);\n }\n this.dispatchEvent(new Event('negotiationneeded'));\n }\n };\n}\n\nexport function shimPeerConnection(window, browserDetails) {\n if (!window.RTCPeerConnection && window.webkitRTCPeerConnection) {\n // very basic support for old versions.\n window.RTCPeerConnection = window.webkitRTCPeerConnection;\n }\n if (!window.RTCPeerConnection) {\n return;\n }\n\n // shim implicit creation of RTCSessionDescription/RTCIceCandidate\n if (browserDetails.version < 53) {\n ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']\n .forEach(function(method) {\n const nativeMethod = window.RTCPeerConnection.prototype[method];\n const methodObj = {[method]() {\n arguments[0] = new ((method === 'addIceCandidate') ?\n window.RTCIceCandidate :\n window.RTCSessionDescription)(arguments[0]);\n return nativeMethod.apply(this, arguments);\n }};\n window.RTCPeerConnection.prototype[method] = methodObj[method];\n });\n }\n}\n\n// Attempt to fix ONN in plan-b mode.\nexport function fixNegotiationNeeded(window, browserDetails) {\n utils.wrapPeerConnectionEvent(window, 'negotiationneeded', e => {\n const pc = e.target;\n if (browserDetails.version < 72 || (pc.getConfiguration &&\n pc.getConfiguration().sdpSemantics === 'plan-b')) {\n if (pc.signalingState !== 'stable') {\n return;\n }\n }\n return e;\n });\n}\n","/*\n * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n/* eslint-env node */\n'use strict';\n\nimport * as utils from '../utils';\n// Edge does not like\n// 1) stun: filtered after 14393 unless ?transport=udp is present\n// 2) turn: that does not have all of turn:host:port?transport=udp\n// 3) turn: with ipv6 addresses\n// 4) turn: occurring muliple times\nexport function filterIceServers(iceServers, edgeVersion) {\n let hasTurn = false;\n iceServers = JSON.parse(JSON.stringify(iceServers));\n return iceServers.filter(server => {\n if (server && (server.urls || server.url)) {\n let urls = server.urls || server.url;\n if (server.url && !server.urls) {\n utils.deprecated('RTCIceServer.url', 'RTCIceServer.urls');\n }\n const isString = typeof urls === 'string';\n if (isString) {\n urls = [urls];\n }\n urls = urls.filter(url => {\n // filter STUN unconditionally.\n if (url.indexOf('stun:') === 0) {\n return false;\n }\n\n const validTurn = url.startsWith('turn') &&\n !url.startsWith('turn:[') &&\n url.includes('transport=udp');\n if (validTurn && !hasTurn) {\n hasTurn = true;\n return true;\n }\n return validTurn && !hasTurn;\n });\n\n delete server.url;\n server.urls = isString ? urls[0] : urls;\n return !!urls.length;\n }\n });\n}\n","/* eslint-env node */\n'use strict';\n\n// SDP helpers.\nvar SDPUtils = {};\n\n// Generate an alphanumeric identifier for cname or mids.\n// TODO: use UUIDs instead? https://gist.github.com/jed/982883\nSDPUtils.generateIdentifier = function() {\n return Math.random().toString(36).substr(2, 10);\n};\n\n// The RTCP CNAME used by all peerconnections from the same JS.\nSDPUtils.localCName = SDPUtils.generateIdentifier();\n\n// Splits SDP into lines, dealing with both CRLF and LF.\nSDPUtils.splitLines = function(blob) {\n return blob.trim().split('\\n').map(function(line) {\n return line.trim();\n });\n};\n// Splits SDP into sessionpart and mediasections. Ensures CRLF.\nSDPUtils.splitSections = function(blob) {\n var parts = blob.split('\\nm=');\n return parts.map(function(part, index) {\n return (index > 0 ? 'm=' + part : part).trim() + '\\r\\n';\n });\n};\n\n// returns the session description.\nSDPUtils.getDescription = function(blob) {\n var sections = SDPUtils.splitSections(blob);\n return sections && sections[0];\n};\n\n// returns the individual media sections.\nSDPUtils.getMediaSections = function(blob) {\n var sections = SDPUtils.splitSections(blob);\n sections.shift();\n return sections;\n};\n\n// Returns lines that start with a certain prefix.\nSDPUtils.matchPrefix = function(blob, prefix) {\n return SDPUtils.splitLines(blob).filter(function(line) {\n return line.indexOf(prefix) === 0;\n });\n};\n\n// Parses an ICE candidate line. Sample input:\n// candidate:702786350 2 udp 41819902 8.8.8.8 60769 typ relay raddr 8.8.8.8\n// rport 55996\"\nSDPUtils.parseCandidate = function(line) {\n var parts;\n // Parse both variants.\n if (line.indexOf('a=candidate:') === 0) {\n parts = line.substring(12).split(' ');\n } else {\n parts = line.substring(10).split(' ');\n }\n\n var candidate = {\n foundation: parts[0],\n component: parseInt(parts[1], 10),\n protocol: parts[2].toLowerCase(),\n priority: parseInt(parts[3], 10),\n ip: parts[4],\n address: parts[4], // address is an alias for ip.\n port: parseInt(parts[5], 10),\n // skip parts[6] == 'typ'\n type: parts[7]\n };\n\n for (var i = 8; i < parts.length; i += 2) {\n switch (parts[i]) {\n case 'raddr':\n candidate.relatedAddress = parts[i + 1];\n break;\n case 'rport':\n candidate.relatedPort = parseInt(parts[i + 1], 10);\n break;\n case 'tcptype':\n candidate.tcpType = parts[i + 1];\n break;\n case 'ufrag':\n candidate.ufrag = parts[i + 1]; // for backward compability.\n candidate.usernameFragment = parts[i + 1];\n break;\n default: // extension handling, in particular ufrag\n candidate[parts[i]] = parts[i + 1];\n break;\n }\n }\n return candidate;\n};\n\n// Translates a candidate object into SDP candidate attribute.\nSDPUtils.writeCandidate = function(candidate) {\n var sdp = [];\n sdp.push(candidate.foundation);\n sdp.push(candidate.component);\n sdp.push(candidate.protocol.toUpperCase());\n sdp.push(candidate.priority);\n sdp.push(candidate.address || candidate.ip);\n sdp.push(candidate.port);\n\n var type = candidate.type;\n sdp.push('typ');\n sdp.push(type);\n if (type !== 'host' && candidate.relatedAddress &&\n candidate.relatedPort) {\n sdp.push('raddr');\n sdp.push(candidate.relatedAddress);\n sdp.push('rport');\n sdp.push(candidate.relatedPort);\n }\n if (candidate.tcpType && candidate.protocol.toLowerCase() === 'tcp') {\n sdp.push('tcptype');\n sdp.push(candidate.tcpType);\n }\n if (candidate.usernameFragment || candidate.ufrag) {\n sdp.push('ufrag');\n sdp.push(candidate.usernameFragment || candidate.ufrag);\n }\n return 'candidate:' + sdp.join(' ');\n};\n\n// Parses an ice-options line, returns an array of option tags.\n// a=ice-options:foo bar\nSDPUtils.parseIceOptions = function(line) {\n return line.substr(14).split(' ');\n};\n\n// Parses an rtpmap line, returns RTCRtpCoddecParameters. Sample input:\n// a=rtpmap:111 opus/48000/2\nSDPUtils.parseRtpMap = function(line) {\n var parts = line.substr(9).split(' ');\n var parsed = {\n payloadType: parseInt(parts.shift(), 10) // was: id\n };\n\n parts = parts[0].split('/');\n\n parsed.name = parts[0];\n parsed.clockRate = parseInt(parts[1], 10); // was: clockrate\n parsed.channels = parts.length === 3 ? parseInt(parts[2], 10) : 1;\n // legacy alias, got renamed back to channels in ORTC.\n parsed.numChannels = parsed.channels;\n return parsed;\n};\n\n// Generate an a=rtpmap line from RTCRtpCodecCapability or\n// RTCRtpCodecParameters.\nSDPUtils.writeRtpMap = function(codec) {\n var pt = codec.payloadType;\n if (codec.preferredPayloadType !== undefined) {\n pt = codec.preferredPayloadType;\n }\n var channels = codec.channels || codec.numChannels || 1;\n return 'a=rtpmap:' + pt + ' ' + codec.name + '/' + codec.clockRate +\n (channels !== 1 ? '/' + channels : '') + '\\r\\n';\n};\n\n// Parses an a=extmap line (headerextension from RFC 5285). Sample input:\n// a=extmap:2 urn:ietf:params:rtp-hdrext:toffset\n// a=extmap:2/sendonly urn:ietf:params:rtp-hdrext:toffset\nSDPUtils.parseExtmap = function(line) {\n var parts = line.substr(9).split(' ');\n return {\n id: parseInt(parts[0], 10),\n direction: parts[0].indexOf('/') > 0 ? parts[0].split('/')[1] : 'sendrecv',\n uri: parts[1]\n };\n};\n\n// Generates a=extmap line from RTCRtpHeaderExtensionParameters or\n// RTCRtpHeaderExtension.\nSDPUtils.writeExtmap = function(headerExtension) {\n return 'a=extmap:' + (headerExtension.id || headerExtension.preferredId) +\n (headerExtension.direction && headerExtension.direction !== 'sendrecv'\n ? '/' + headerExtension.direction\n : '') +\n ' ' + headerExtension.uri + '\\r\\n';\n};\n\n// Parses an ftmp line, returns dictionary. Sample input:\n// a=fmtp:96 vbr=on;cng=on\n// Also deals with vbr=on; cng=on\nSDPUtils.parseFmtp = function(line) {\n var parsed = {};\n var kv;\n var parts = line.substr(line.indexOf(' ') + 1).split(';');\n for (var j = 0; j < parts.length; j++) {\n kv = parts[j].trim().split('=');\n parsed[kv[0].trim()] = kv[1];\n }\n return parsed;\n};\n\n// Generates an a=ftmp line from RTCRtpCodecCapability or RTCRtpCodecParameters.\nSDPUtils.writeFmtp = function(codec) {\n var line = '';\n var pt = codec.payloadType;\n if (codec.preferredPayloadType !== undefined) {\n pt = codec.preferredPayloadType;\n }\n if (codec.parameters && Object.keys(codec.parameters).length) {\n var params = [];\n Object.keys(codec.parameters).forEach(function(param) {\n if (codec.parameters[param]) {\n params.push(param + '=' + codec.parameters[param]);\n } else {\n params.push(param);\n }\n });\n line += 'a=fmtp:' + pt + ' ' + params.join(';') + '\\r\\n';\n }\n return line;\n};\n\n// Parses an rtcp-fb line, returns RTCPRtcpFeedback object. Sample input:\n// a=rtcp-fb:98 nack rpsi\nSDPUtils.parseRtcpFb = function(line) {\n var parts = line.substr(line.indexOf(' ') + 1).split(' ');\n return {\n type: parts.shift(),\n parameter: parts.join(' ')\n };\n};\n// Generate a=rtcp-fb lines from RTCRtpCodecCapability or RTCRtpCodecParameters.\nSDPUtils.writeRtcpFb = function(codec) {\n var lines = '';\n var pt = codec.payloadType;\n if (codec.preferredPayloadType !== undefined) {\n pt = codec.preferredPayloadType;\n }\n if (codec.rtcpFeedback && codec.rtcpFeedback.length) {\n // FIXME: special handling for trr-int?\n codec.rtcpFeedback.forEach(function(fb) {\n lines += 'a=rtcp-fb:' + pt + ' ' + fb.type +\n (fb.parameter && fb.parameter.length ? ' ' + fb.parameter : '') +\n '\\r\\n';\n });\n }\n return lines;\n};\n\n// Parses an RFC 5576 ssrc media attribute. Sample input:\n// a=ssrc:3735928559 cname:something\nSDPUtils.parseSsrcMedia = function(line) {\n var sp = line.indexOf(' ');\n var parts = {\n ssrc: parseInt(line.substr(7, sp - 7), 10)\n };\n var colon = line.indexOf(':', sp);\n if (colon > -1) {\n parts.attribute = line.substr(sp + 1, colon - sp - 1);\n parts.value = line.substr(colon + 1);\n } else {\n parts.attribute = line.substr(sp + 1);\n }\n return parts;\n};\n\nSDPUtils.parseSsrcGroup = function(line) {\n var parts = line.substr(13).split(' ');\n return {\n semantics: parts.shift(),\n ssrcs: parts.map(function(ssrc) {\n return parseInt(ssrc, 10);\n })\n };\n};\n\n// Extracts the MID (RFC 5888) from a media section.\n// returns the MID or undefined if no mid line was found.\nSDPUtils.getMid = function(mediaSection) {\n var mid = SDPUtils.matchPrefix(mediaSection, 'a=mid:')[0];\n if (mid) {\n return mid.substr(6);\n }\n};\n\nSDPUtils.parseFingerprint = function(line) {\n var parts = line.substr(14).split(' ');\n return {\n algorithm: parts[0].toLowerCase(), // algorithm is case-sensitive in Edge.\n value: parts[1]\n };\n};\n\n// Extracts DTLS parameters from SDP media section or sessionpart.\n// FIXME: for consistency with other functions this should only\n// get the fingerprint line as input. See also getIceParameters.\nSDPUtils.getDtlsParameters = function(mediaSection, sessionpart) {\n var lines = SDPUtils.matchPrefix(mediaSection + sessionpart,\n 'a=fingerprint:');\n // Note: a=setup line is ignored since we use the 'auto' role.\n // Note2: 'algorithm' is not case sensitive except in Edge.\n return {\n role: 'auto',\n fingerprints: lines.map(SDPUtils.parseFingerprint)\n };\n};\n\n// Serializes DTLS parameters to SDP.\nSDPUtils.writeDtlsParameters = function(params, setupType) {\n var sdp = 'a=setup:' + setupType + '\\r\\n';\n params.fingerprints.forEach(function(fp) {\n sdp += 'a=fingerprint:' + fp.algorithm + ' ' + fp.value + '\\r\\n';\n });\n return sdp;\n};\n\n// Parses a=crypto lines into\n// https://rawgit.com/aboba/edgertc/master/msortc-rs4.html#dictionary-rtcsrtpsdesparameters-members\nSDPUtils.parseCryptoLine = function(line) {\n var parts = line.substr(9).split(' ');\n return {\n tag: parseInt(parts[0], 10),\n cryptoSuite: parts[1],\n keyParams: parts[2],\n sessionParams: parts.slice(3),\n };\n};\n\nSDPUtils.writeCryptoLine = function(parameters) {\n return 'a=crypto:' + parameters.tag + ' ' +\n parameters.cryptoSuite + ' ' +\n (typeof parameters.keyParams === 'object'\n ? SDPUtils.writeCryptoKeyParams(parameters.keyParams)\n : parameters.keyParams) +\n (parameters.sessionParams ? ' ' + parameters.sessionParams.join(' ') : '') +\n '\\r\\n';\n};\n\n// Parses the crypto key parameters into\n// https://rawgit.com/aboba/edgertc/master/msortc-rs4.html#rtcsrtpkeyparam*\nSDPUtils.parseCryptoKeyParams = function(keyParams) {\n if (keyParams.indexOf('inline:') !== 0) {\n return null;\n }\n var parts = keyParams.substr(7).split('|');\n return {\n keyMethod: 'inline',\n keySalt: parts[0],\n lifeTime: parts[1],\n mkiValue: parts[2] ? parts[2].split(':')[0] : undefined,\n mkiLength: parts[2] ? parts[2].split(':')[1] : undefined,\n };\n};\n\nSDPUtils.writeCryptoKeyParams = function(keyParams) {\n return keyParams.keyMethod + ':'\n + keyParams.keySalt +\n (keyParams.lifeTime ? '|' + keyParams.lifeTime : '') +\n (keyParams.mkiValue && keyParams.mkiLength\n ? '|' + keyParams.mkiValue + ':' + keyParams.mkiLength\n : '');\n};\n\n// Extracts all SDES paramters.\nSDPUtils.getCryptoParameters = function(mediaSection, sessionpart) {\n var lines = SDPUtils.matchPrefix(mediaSection + sessionpart,\n 'a=crypto:');\n return lines.map(SDPUtils.parseCryptoLine);\n};\n\n// Parses ICE information from SDP media section or sessionpart.\n// FIXME: for consistency with other functions this should only\n// get the ice-ufrag and ice-pwd lines as input.\nSDPUtils.getIceParameters = function(mediaSection, sessionpart) {\n var ufrag = SDPUtils.matchPrefix(mediaSection + sessionpart,\n 'a=ice-ufrag:')[0];\n var pwd = SDPUtils.matchPrefix(mediaSection + sessionpart,\n 'a=ice-pwd:')[0];\n if (!(ufrag && pwd)) {\n return null;\n }\n return {\n usernameFragment: ufrag.substr(12),\n password: pwd.substr(10),\n };\n};\n\n// Serializes ICE parameters to SDP.\nSDPUtils.writeIceParameters = function(params) {\n return 'a=ice-ufrag:' + params.usernameFragment + '\\r\\n' +\n 'a=ice-pwd:' + params.password + '\\r\\n';\n};\n\n// Parses the SDP media section and returns RTCRtpParameters.\nSDPUtils.parseRtpParameters = function(mediaSection) {\n var description = {\n codecs: [],\n headerExtensions: [],\n fecMechanisms: [],\n rtcp: []\n };\n var lines = SDPUtils.splitLines(mediaSection);\n var mline = lines[0].split(' ');\n for (var i = 3; i < mline.length; i++) { // find all codecs from mline[3..]\n var pt = mline[i];\n var rtpmapline = SDPUtils.matchPrefix(\n mediaSection, 'a=rtpmap:' + pt + ' ')[0];\n if (rtpmapline) {\n var codec = SDPUtils.parseRtpMap(rtpmapline);\n var fmtps = SDPUtils.matchPrefix(\n mediaSection, 'a=fmtp:' + pt + ' ');\n // Only the first a=fmtp:<pt> is considered.\n codec.parameters = fmtps.length ? SDPUtils.parseFmtp(fmtps[0]) : {};\n codec.rtcpFeedback = SDPUtils.matchPrefix(\n mediaSection, 'a=rtcp-fb:' + pt + ' ')\n .map(SDPUtils.parseRtcpFb);\n description.codecs.push(codec);\n // parse FEC mechanisms from rtpmap lines.\n switch (codec.name.toUpperCase()) {\n case 'RED':\n case 'ULPFEC':\n description.fecMechanisms.push(codec.name.toUpperCase());\n break;\n default: // only RED and ULPFEC are recognized as FEC mechanisms.\n break;\n }\n }\n }\n SDPUtils.matchPrefix(mediaSection, 'a=extmap:').forEach(function(line) {\n description.headerExtensions.push(SDPUtils.parseExtmap(line));\n });\n // FIXME: parse rtcp.\n return description;\n};\n\n// Generates parts of the SDP media section describing the capabilities /\n// parameters.\nSDPUtils.writeRtpDescription = function(kind, caps) {\n var sdp = '';\n\n // Build the mline.\n sdp += 'm=' + kind + ' ';\n sdp += caps.codecs.length > 0 ? '9' : '0'; // reject if no codecs.\n sdp += ' UDP/TLS/RTP/SAVPF ';\n sdp += caps.codecs.map(function(codec) {\n if (codec.preferredPayloadType !== undefined) {\n return codec.preferredPayloadType;\n }\n return codec.payloadType;\n }).join(' ') + '\\r\\n';\n\n sdp += 'c=IN IP4 0.0.0.0\\r\\n';\n sdp += 'a=rtcp:9 IN IP4 0.0.0.0\\r\\n';\n\n // Add a=rtpmap lines for each codec. Also fmtp and rtcp-fb.\n caps.codecs.forEach(function(codec) {\n sdp += SDPUtils.writeRtpMap(codec);\n sdp += SDPUtils.writeFmtp(codec);\n sdp += SDPUtils.writeRtcpFb(codec);\n });\n var maxptime = 0;\n caps.codecs.forEach(function(codec) {\n if (codec.maxptime > maxptime) {\n maxptime = codec.maxptime;\n }\n });\n if (maxptime > 0) {\n sdp += 'a=maxptime:' + maxptime + '\\r\\n';\n }\n sdp += 'a=rtcp-mux\\r\\n';\n\n if (caps.headerExtensions) {\n caps.headerExtensions.forEach(function(extension) {\n sdp += SDPUtils.writeExtmap(extension);\n });\n }\n // FIXME: write fecMechanisms.\n return sdp;\n};\n\n// Parses the SDP media section and returns an array of\n// RTCRtpEncodingParameters.\nSDPUtils.parseRtpEncodingParameters = function(mediaSection) {\n var encodingParameters = [];\n var description = SDPUtils.parseRtpParameters(mediaSection);\n var hasRed = description.fecMechanisms.indexOf('RED') !== -1;\n var hasUlpfec = description.fecMechanisms.indexOf('ULPFEC') !== -1;\n\n // filter a=ssrc:... cname:, ignore PlanB-msid\n var ssrcs = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')\n .map(function(line) {\n return SDPUtils.parseSsrcMedia(line);\n })\n .filter(function(parts) {\n return parts.attribute === 'cname';\n });\n var primarySsrc = ssrcs.length > 0 && ssrcs[0].ssrc;\n var secondarySsrc;\n\n var flows = SDPUtils.matchPrefix(mediaSection, 'a=ssrc-group:FID')\n .map(function(line) {\n var parts = line.substr(17).split(' ');\n return parts.map(function(part) {\n return parseInt(part, 10);\n });\n });\n if (flows.length > 0 && flows[0].length > 1 && flows[0][0] === primarySsrc) {\n secondarySsrc = flows[0][1];\n }\n\n description.codecs.forEach(function(codec) {\n if (codec.name.toUpperCase() === 'RTX' && codec.parameters.apt) {\n var encParam = {\n ssrc: primarySsrc,\n codecPayloadType: parseInt(codec.parameters.apt, 10)\n };\n if (primarySsrc && secondarySsrc) {\n encParam.rtx = {ssrc: secondarySsrc};\n }\n encodingParameters.push(encParam);\n if (hasRed) {\n encParam = JSON.parse(JSON.stringify(encParam));\n encParam.fec = {\n ssrc: primarySsrc,\n mechanism: hasUlpfec ? 'red+ulpfec' : 'red'\n };\n encodingParameters.push(encParam);\n }\n }\n });\n if (encodingParameters.length === 0 && primarySsrc) {\n encodingParameters.push({\n ssrc: primarySsrc\n });\n }\n\n // we support both b=AS and b=TIAS but interpret AS as TIAS.\n var bandwidth = SDPUtils.matchPrefix(mediaSection, 'b=');\n if (bandwidth.length) {\n if (bandwidth[0].indexOf('b=TIAS:') === 0) {\n bandwidth = parseInt(bandwidth[0].substr(7), 10);\n } else if (bandwidth[0].indexOf('b=AS:') === 0) {\n // use formula from JSEP to convert b=AS to TIAS value.\n bandwidth = parseInt(bandwidth[0].substr(5), 10) * 1000 * 0.95\n - (50 * 40 * 8);\n } else {\n bandwidth = undefined;\n }\n encodingParameters.forEach(function(params) {\n params.maxBitrate = bandwidth;\n });\n }\n return encodingParameters;\n};\n\n// parses http://draft.ortc.org/#rtcrtcpparameters*\nSDPUtils.parseRtcpParameters = function(mediaSection) {\n var rtcpParameters = {};\n\n // Gets the first SSRC. Note tha with RTX there might be multiple\n // SSRCs.\n var remoteSsrc = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')\n .map(function(line) {\n return SDPUtils.parseSsrcMedia(line);\n })\n .filter(function(obj) {\n return obj.attribute === 'cname';\n })[0];\n if (remoteSsrc) {\n rtcpParameters.cname = remoteSsrc.value;\n rtcpParameters.ssrc = remoteSsrc.ssrc;\n }\n\n // Edge uses the compound attribute instead of reducedSize\n // compound is !reducedSize\n var rsize = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-rsize');\n rtcpParameters.reducedSize = rsize.length > 0;\n rtcpParameters.compound = rsize.length === 0;\n\n // parses the rtcp-mux attrіbute.\n // Note that Edge does not support unmuxed RTCP.\n var mux = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-mux');\n rtcpParameters.mux = mux.length > 0;\n\n return rtcpParameters;\n};\n\n// parses either a=msid: or a=ssrc:... msid lines and returns\n// the id of the MediaStream and MediaStreamTrack.\nSDPUtils.parseMsid = function(mediaSection) {\n var parts;\n var spec = SDPUtils.matchPrefix(mediaSection, 'a=msid:');\n if (spec.length === 1) {\n parts = spec[0].substr(7).split(' ');\n return {stream: parts[0], track: parts[1]};\n }\n var planB = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')\n .map(function(line) {\n return SDPUtils.parseSsrcMedia(line);\n })\n .filter(function(msidParts) {\n return msidParts.attribute === 'msid';\n });\n if (planB.length > 0) {\n parts = planB[0].value.split(' ');\n return {stream: parts[0], track: parts[1]};\n }\n};\n\n// SCTP\n// parses draft-ietf-mmusic-sctp-sdp-26 first and falls back\n// to draft-ietf-mmusic-sctp-sdp-05\nSDPUtils.parseSctpDescription = function(mediaSection) {\n var mline = SDPUtils.parseMLine(mediaSection);\n var maxSizeLine = SDPUtils.matchPrefix(mediaSection, 'a=max-message-size:');\n var maxMessageSize;\n if (maxSizeLine.length > 0) {\n maxMessageSize = parseInt(maxSizeLine[0].substr(19), 10);\n }\n if (isNaN(maxMessageSize)) {\n maxMessageSize = 65536;\n }\n var sctpPort = SDPUtils.matchPrefix(mediaSection, 'a=sctp-port:');\n if (sctpPort.length > 0) {\n return {\n port: parseInt(sctpPort[0].substr(12), 10),\n protocol: mline.fmt,\n maxMessageSize: maxMessageSize\n };\n }\n var sctpMapLines = SDPUtils.matchPrefix(mediaSection, 'a=sctpmap:');\n if (sctpMapLines.length > 0) {\n var parts = SDPUtils.matchPrefix(mediaSection, 'a=sctpmap:')[0]\n .substr(10)\n .split(' ');\n return {\n port: parseInt(parts[0], 10),\n protocol: parts[1],\n maxMessageSize: maxMessageSize\n };\n }\n};\n\n// SCTP\n// outputs the draft-ietf-mmusic-sctp-sdp-26 version that all browsers\n// support by now receiving in this format, unless we originally parsed\n// as the draft-ietf-mmusic-sctp-sdp-05 format (indicated by the m-line\n// protocol of DTLS/SCTP -- without UDP/ or TCP/)\nSDPUtils.writeSctpDescription = function(media, sctp) {\n var output = [];\n if (media.protocol !== 'DTLS/SCTP') {\n output = [\n 'm=' + media.kind + ' 9 ' + media.protocol + ' ' + sctp.protocol + '\\r\\n',\n 'c=IN IP4 0.0.0.0\\r\\n',\n 'a=sctp-port:' + sctp.port + '\\r\\n'\n ];\n } else {\n output = [\n 'm=' + media.kind + ' 9 ' + media.protocol + ' ' + sctp.port + '\\r\\n',\n 'c=IN IP4 0.0.0.0\\r\\n',\n 'a=sctpmap:' + sctp.port + ' ' + sctp.protocol + ' 65535\\r\\n'\n ];\n }\n if (sctp.maxMessageSize !== undefined) {\n output.push('a=max-message-size:' + sctp.maxMessageSize + '\\r\\n');\n }\n return output.join('');\n};\n\n// Generate a session ID for SDP.\n// https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-20#section-5.2.1\n// recommends using a cryptographically random +ve 64-bit value\n// but right now this should be acceptable and within the right range\nSDPUtils.generateSessionId = function() {\n return Math.random().toString().substr(2, 21);\n};\n\n// Write boilder plate for start of SDP\n// sessId argument is optional - if not supplied it will\n// be generated randomly\n// sessVersion is optional and defaults to 2\n// sessUser is optional and defaults to 'thisisadapterortc'\nSDPUtils.writeSessionBoilerplate = function(sessId, sessVer, sessUser) {\n var sessionId;\n var version = sessVer !== undefined ? sessVer : 2;\n if (sessId) {\n sessionId = sessId;\n } else {\n sessionId = SDPUtils.generateSessionId();\n }\n var user = sessUser || 'thisisadapterortc';\n // FIXME: sess-id should be an NTP timestamp.\n return 'v=0\\r\\n' +\n 'o=' + user + ' ' + sessionId + ' ' + version +\n ' IN IP4 127.0.0.1\\r\\n' +\n 's=-\\r\\n' +\n 't=0 0\\r\\n';\n};\n\nSDPUtils.writeMediaSection = function(transceiver, caps, type, stream) {\n var sdp = SDPUtils.writeRtpDescription(transceiver.kind, caps);\n\n // Map ICE parameters (ufrag, pwd) to SDP.\n sdp += SDPUtils.writeIceParameters(\n transceiver.iceGatherer.getLocalParameters());\n\n // Map DTLS parameters to SDP.\n sdp += SDPUtils.writeDtlsParameters(\n transceiver.dtlsTransport.getLocalParameters(),\n type === 'offer' ? 'actpass' : 'active');\n\n sdp += 'a=mid:' + transceiver.mid + '\\r\\n';\n\n if (transceiver.direction) {\n sdp += 'a=' + transceiver.direction + '\\r\\n';\n } else if (transceiver.rtpSender && transceiver.rtpReceiver) {\n sdp += 'a=sendrecv\\r\\n';\n } else if (transceiver.rtpSender) {\n sdp += 'a=sendonly\\r\\n';\n } else if (transceiver.rtpReceiver) {\n sdp += 'a=recvonly\\r\\n';\n } else {\n sdp += 'a=inactive\\r\\n';\n }\n\n if (transceiver.rtpSender) {\n // spec.\n var msid = 'msid:' + stream.id + ' ' +\n transceiver.rtpSender.track.id + '\\r\\n';\n sdp += 'a=' + msid;\n\n // for Chrome.\n sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc +\n ' ' + msid;\n if (transceiver.sendEncodingParameters[0].rtx) {\n sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc +\n ' ' + msid;\n sdp += 'a=ssrc-group:FID ' +\n transceiver.sendEncodingParameters[0].ssrc + ' ' +\n transceiver.sendEncodingParameters[0].rtx.ssrc +\n '\\r\\n';\n }\n }\n // FIXME: this should be written by writeRtpDescription.\n sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc +\n ' cname:' + SDPUtils.localCName + '\\r\\n';\n if (transceiver.rtpSender && transceiver.sendEncodingParameters[0].rtx) {\n sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc +\n ' cname:' + SDPUtils.localCName + '\\r\\n';\n }\n return sdp;\n};\n\n// Gets the direction from the mediaSection or the sessionpart.\nSDPUtils.getDirection = function(mediaSection, sessionpart) {\n // Look for sendrecv, sendonly, recvonly, inactive, default to sendrecv.\n var lines = SDPUtils.splitLines(mediaSection);\n for (var i = 0; i < lines.length; i++) {\n switch (lines[i]) {\n case 'a=sendrecv':\n case 'a=sendonly':\n case 'a=recvonly':\n case 'a=inactive':\n return lines[i].substr(2);\n default:\n // FIXME: What should happen here?\n }\n }\n if (sessionpart) {\n return SDPUtils.getDirection(sessionpart);\n }\n return 'sendrecv';\n};\n\nSDPUtils.getKind = function(mediaSection) {\n var lines = SDPUtils.splitLines(mediaSection);\n var mline = lines[0].split(' ');\n return mline[0].substr(2);\n};\n\nSDPUtils.isRejected = function(mediaSection) {\n return mediaSection.split(' ', 2)[1] === '0';\n};\n\nSDPUtils.parseMLine = function(mediaSection) {\n var lines = SDPUtils.splitLines(mediaSection);\n var parts = lines[0].substr(2).split(' ');\n return {\n kind: parts[0],\n port: parseInt(parts[1], 10),\n protocol: parts[2],\n fmt: parts.slice(3).join(' ')\n };\n};\n\nSDPUtils.parseOLine = function(mediaSection) {\n var line = SDPUtils.matchPrefix(mediaSection, 'o=')[0];\n var parts = line.substr(2).split(' ');\n return {\n username: parts[0],\n sessionId: parts[1],\n sessionVersion: parseInt(parts[2], 10),\n netType: parts[3],\n addressType: parts[4],\n address: parts[5]\n };\n};\n\n// a very naive interpretation of a valid SDP.\nSDPUtils.isValidSDP = function(blob) {\n if (typeof blob !== 'string' || blob.length === 0) {\n return false;\n }\n var lines = SDPUtils.splitLines(blob);\n for (var i = 0; i < lines.length; i++) {\n if (lines[i].length < 2 || lines[i].charAt(1) !== '=') {\n return false;\n }\n // TODO: check the modifier a bit more.\n }\n return true;\n};\n\n// Expose public methods.\nif (typeof module === 'object') {\n module.exports = SDPUtils;\n}\n","/*\n * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n /* eslint-env node */\n'use strict';\n\nvar SDPUtils = require('sdp');\n\nfunction fixStatsType(stat) {\n return {\n inboundrtp: 'inbound-rtp',\n outboundrtp: 'outbound-rtp',\n candidatepair: 'candidate-pair',\n localcandidate: 'local-candidate',\n remotecandidate: 'remote-candidate'\n }[stat.type] || stat.type;\n}\n\nfunction writeMediaSection(transceiver, caps, type, stream, dtlsRole) {\n var sdp = SDPUtils.writeRtpDescription(transceiver.kind, caps);\n\n // Map ICE parameters (ufrag, pwd) to SDP.\n sdp += SDPUtils.writeIceParameters(\n transceiver.iceGatherer.getLocalParameters());\n\n // Map DTLS parameters to SDP.\n sdp += SDPUtils.writeDtlsParameters(\n transceiver.dtlsTransport.getLocalParameters(),\n type === 'offer' ? 'actpass' : dtlsRole || 'active');\n\n sdp += 'a=mid:' + transceiver.mid + '\\r\\n';\n\n if (transceiver.rtpSender && transceiver.rtpReceiver) {\n sdp += 'a=sendrecv\\r\\n';\n } else if (transceiver.rtpSender) {\n sdp += 'a=sendonly\\r\\n';\n } else if (transceiver.rtpReceiver) {\n sdp += 'a=recvonly\\r\\n';\n } else {\n sdp += 'a=inactive\\r\\n';\n }\n\n if (transceiver.rtpSender) {\n var trackId = transceiver.rtpSender._initialTrackId ||\n transceiver.rtpSender.track.id;\n transceiver.rtpSender._initialTrackId = trackId;\n // spec.\n var msid = 'msid:' + (stream ? stream.id : '-') + ' ' +\n trackId + '\\r\\n';\n sdp += 'a=' + msid;\n // for Chrome. Legacy should no longer be required.\n sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc +\n ' ' + msid;\n\n // RTX\n if (transceiver.sendEncodingParameters[0].rtx) {\n sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc +\n ' ' + msid;\n sdp += 'a=ssrc-group:FID ' +\n transceiver.sendEncodingParameters[0].ssrc + ' ' +\n transceiver.sendEncodingParameters[0].rtx.ssrc +\n '\\r\\n';\n }\n }\n // FIXME: this should be written by writeRtpDescription.\n sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc +\n ' cname:' + SDPUtils.localCName + '\\r\\n';\n if (transceiver.rtpSender && transceiver.sendEncodingParameters[0].rtx) {\n sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc +\n ' cname:' + SDPUtils.localCName + '\\r\\n';\n }\n return sdp;\n}\n\n// Edge does not like\n// 1) stun: filtered after 14393 unless ?transport=udp is present\n// 2) turn: that does not have all of turn:host:port?transport=udp\n// 3) turn: with ipv6 addresses\n// 4) turn: occurring muliple times\nfunction filterIceServers(iceServers, edgeVersion) {\n var hasTurn = false;\n iceServers = JSON.parse(JSON.stringify(iceServers));\n return iceServers.filter(function(server) {\n if (server && (server.urls || server.url)) {\n var urls = server.urls || server.url;\n if (server.url && !server.urls) {\n console.warn('RTCIceServer.url is deprecated! Use urls instead.');\n }\n var isString = typeof urls === 'string';\n if (isString) {\n urls = [urls];\n }\n urls = urls.filter(function(url) {\n var validTurn = url.indexOf('turn:') === 0 &&\n url.indexOf('transport=udp') !== -1 &&\n url.indexOf('turn:[') === -1 &&\n !hasTurn;\n\n if (validTurn) {\n hasTurn = true;\n return true;\n }\n return url.indexOf('stun:') === 0 && edgeVersion >= 14393 &&\n url.indexOf('?transport=udp') === -1;\n });\n\n delete server.url;\n server.urls = isString ? urls[0] : urls;\n return !!urls.length;\n }\n });\n}\n\n// Determines the intersection of local and remote capabilities.\nfunction getCommonCapabilities(localCapabilities, remoteCapabilities) {\n var commonCapabilities = {\n codecs: [],\n headerExtensions: [],\n fecMechanisms: []\n };\n\n var findCodecByPayloadType = function(pt, codecs) {\n pt = parseInt(pt, 10);\n for (var i = 0; i < codecs.length; i++) {\n if (codecs[i].payloadType === pt ||\n codecs[i].preferredPayloadType === pt) {\n return codecs[i];\n }\n }\n };\n\n var rtxCapabilityMatches = function(lRtx, rRtx, lCodecs, rCodecs) {\n var lCodec = findCodecByPayloadType(lRtx.parameters.apt, lCodecs);\n var rCodec = findCodecByPayloadType(rRtx.parameters.apt, rCodecs);\n return lCodec && rCodec &&\n lCodec.name.toLowerCase() === rCodec.name.toLowerCase();\n };\n\n localCapabilities.codecs.forEach(function(lCodec) {\n for (var i = 0; i < remoteCapabilities.codecs.length; i++) {\n var rCodec = remoteCapabilities.codecs[i];\n if (lCodec.name.toLowerCase() === rCodec.name.toLowerCase() &&\n lCodec.clockRate === rCodec.clockRate) {\n if (lCodec.name.toLowerCase() === 'rtx' &&\n lCodec.parameters && rCodec.parameters.apt) {\n // for RTX we need to find the local rtx that has a apt\n // which points to the same local codec as the remote one.\n if (!rtxCapabilityMatches(lCodec, rCodec,\n localCapabilities.codecs, remoteCapabilities.codecs)) {\n continue;\n }\n }\n rCodec = JSON.parse(JSON.stringify(rCodec)); // deepcopy\n // number of channels is the highest common number of channels\n rCodec.numChannels = Math.min(lCodec.numChannels,\n rCodec.numChannels);\n // push rCodec so we reply with offerer payload type\n commonCapabilities.codecs.push(rCodec);\n\n // determine common feedback mechanisms\n rCodec.rtcpFeedback = rCodec.rtcpFeedback.filter(function(fb) {\n for (var j = 0; j < lCodec.rtcpFeedback.length; j++) {\n if (lCodec.rtcpFeedback[j].type === fb.type &&\n lCodec.rtcpFeedback[j].parameter === fb.parameter) {\n return true;\n }\n }\n return false;\n });\n // FIXME: also need to determine .parameters\n // see https://github.com/openpeer/ortc/issues/569\n break;\n }\n }\n });\n\n localCapabilities.headerExtensions.forEach(function(lHeaderExtension) {\n for (var i = 0; i < remoteCapabilities.headerExtensions.length;\n i++) {\n var rHeaderExtension = remoteCapabilities.headerExtensions[i];\n if (lHeaderExtension.uri === rHeaderExtension.uri) {\n commonCapabilities.headerExtensions.push(rHeaderExtension);\n break;\n }\n }\n });\n\n // FIXME: fecMechanisms\n return commonCapabilities;\n}\n\n// is action=setLocalDescription with type allowed in signalingState\nfunction isActionAllowedInSignalingState(action, type, signalingState) {\n return {\n offer: {\n setLocalDescription: ['stable', 'have-local-offer'],\n setRemoteDescription: ['stable', 'have-remote-offer']\n },\n answer: {\n setLocalDescription: ['have-remote-offer', 'have-local-pranswer'],\n setRemoteDescription: ['have-local-offer', 'have-remote-pranswer']\n }\n }[type][action].indexOf(signalingState) !== -1;\n}\n\nfunction maybeAddCandidate(iceTransport, candidate) {\n // Edge's internal representation adds some fields therefore\n // not all fieldѕ are taken into account.\n var alreadyAdded = iceTransport.getRemoteCandidates()\n .find(function(remoteCandidate) {\n return candidate.foundation === remoteCandidate.foundation &&\n candidate.ip === remoteCandidate.ip &&\n candidate.port === remoteCandidate.port &&\n candidate.priority === remoteCandidate.priority &&\n candidate.protocol === remoteCandidate.protocol &&\n candidate.type === remoteCandidate.type;\n });\n if (!alreadyAdded) {\n iceTransport.addRemoteCandidate(candidate);\n }\n return !alreadyAdded;\n}\n\n\nfunction makeError(name, description) {\n var e = new Error(description);\n e.name = name;\n // legacy error codes from https://heycam.github.io/webidl/#idl-DOMException-error-names\n e.code = {\n NotSupportedError: 9,\n InvalidStateError: 11,\n InvalidAccessError: 15,\n TypeError: undefined,\n OperationError: undefined\n }[name];\n return e;\n}\n\nmodule.exports = function(window, edgeVersion) {\n // https://w3c.github.io/mediacapture-main/#mediastream\n // Helper function to add the track to the stream and\n // dispatch the event ourselves.\n function addTrackToStreamAndFireEvent(track, stream) {\n stream.addTrack(track);\n stream.dispatchEvent(new window.MediaStreamTrackEvent('addtrack',\n {track: track}));\n }\n\n function removeTrackFromStreamAndFireEvent(track, stream) {\n stream.removeTrack(track);\n stream.dispatchEvent(new window.MediaStreamTrackEvent('removetrack',\n {track: track}));\n }\n\n function fireAddTrack(pc, track, receiver, streams) {\n var trackEvent = new Event('track');\n trackEvent.track = track;\n trackEvent.receiver = receiver;\n trackEvent.transceiver = {receiver: receiver};\n trackEvent.streams = streams;\n window.setTimeout(function() {\n pc._dispatchEvent('track', trackEvent);\n });\n }\n\n var RTCPeerConnection = function(config) {\n var pc = this;\n\n var _eventTarget = document.createDocumentFragment();\n ['addEventListener', 'removeEventListener', 'dispatchEvent']\n .forEach(function(method) {\n pc[method] = _eventTarget[method].bind(_eventTarget);\n });\n\n this.canTrickleIceCandidates = null;\n\n this.needNegotiation = false;\n\n this.localStreams = [];\n this.remoteStreams = [];\n\n this._localDescription = null;\n this._remoteDescription = null;\n\n this.signalingState = 'stable';\n this.iceConnectionState = 'new';\n this.connectionState = 'new';\n this.iceGatheringState = 'new';\n\n config = JSON.parse(JSON.stringify(config || {}));\n\n this.usingBundle = config.bundlePolicy === 'max-bundle';\n if (config.rtcpMuxPolicy === 'negotiate') {\n throw(makeError('NotSupportedError',\n 'rtcpMuxPolicy \\'negotiate\\' is not supported'));\n } else if (!config.rtcpMuxPolicy) {\n config.rtcpMuxPolicy = 'require';\n }\n\n switch (config.iceTransportPolicy) {\n case 'all':\n case 'relay':\n break;\n default:\n config.iceTransportPolicy = 'all';\n break;\n }\n\n switch (config.bundlePolicy) {\n case 'balanced':\n case 'max-compat':\n case 'max-bundle':\n break;\n default:\n config.bundlePolicy = 'balanced';\n break;\n }\n\n config.iceServers = filterIceServers(config.iceServers || [], edgeVersion);\n\n this._iceGatherers = [];\n if (config.iceCandidatePoolSize) {\n for (var i = config.iceCandidatePoolSize; i > 0; i--) {\n this._iceGatherers.push(new window.RTCIceGatherer({\n iceServers: config.iceServers,\n gatherPolicy: config.iceTransportPolicy\n }));\n }\n } else {\n config.iceCandidatePoolSize = 0;\n }\n\n this._config = config;\n\n // per-track iceGathers, iceTransports, dtlsTransports, rtpSenders, ...\n // everything that is needed to describe a SDP m-line.\n this.transceivers = [];\n\n this._sdpSessionId = SDPUtils.generateSessionId();\n this._sdpSessionVersion = 0;\n\n this._dtlsRole = undefined; // role for a=setup to use in answers.\n\n this._isClosed = false;\n };\n\n Object.defineProperty(RTCPeerConnection.prototype, 'localDescription', {\n configurable: true,\n get: function() {\n return this._localDescription;\n }\n });\n Object.defineProperty(RTCPeerConnection.prototype, 'remoteDescription', {\n configurable: true,\n get: function() {\n return this._remoteDescription;\n }\n });\n\n // set up event handlers on prototype\n RTCPeerConnection.prototype.onicecandidate = null;\n RTCPeerConnection.prototype.onaddstream = null;\n RTCPeerConnection.prototype.ontrack = null;\n RTCPeerConnection.prototype.onremovestream = null;\n RTCPeerConnection.prototype.onsignalingstatechange = null;\n RTCPeerConnection.prototype.oniceconnectionstatechange = null;\n RTCPeerConnection.prototype.onconnectionstatechange = null;\n RTCPeerConnection.prototype.onicegatheringstatechange = null;\n RTCPeerConnection.prototype.onnegotiationneeded = null;\n RTCPeerConnection.prototype.ondatachannel = null;\n\n RTCPeerConnection.prototype._dispatchEvent = function(name, event) {\n if (this._isClosed) {\n return;\n }\n this.dispatchEvent(event);\n if (typeof this['on' + name] === 'function') {\n this['on' + name](event);\n }\n };\n\n RTCPeerConnection.prototype._emitGatheringStateChange = function() {\n var event = new Event('icegatheringstatechange');\n this._dispatchEvent('icegatheringstatechange', event);\n };\n\n RTCPeerConnection.prototype.getConfiguration = function() {\n return this._config;\n };\n\n RTCPeerConnection.prototype.getLocalStreams = function() {\n return this.localStreams;\n };\n\n RTCPeerConnection.prototype.getRemoteStreams = function() {\n return this.remoteStreams;\n };\n\n // internal helper to create a transceiver object.\n // (which is not yet the same as the WebRTC 1.0 transceiver)\n RTCPeerConnection.prototype._createTransceiver = function(kind, doNotAdd) {\n var hasBundleTransport = this.transceivers.length > 0;\n var transceiver = {\n track: null,\n iceGatherer: null,\n iceTransport: null,\n dtlsTransport: null,\n localCapabilities: null,\n remoteCapabilities: null,\n rtpSender: null,\n rtpReceiver: null,\n kind: kind,\n mid: null,\n sendEncodingParameters: null,\n recvEncodingParameters: null,\n stream: null,\n associatedRemoteMediaStreams: [],\n wantReceive: true\n };\n if (this.usingBundle && hasBundleTransport) {\n transceiver.iceTransport = this.transceivers[0].iceTransport;\n transceiver.dtlsTransport = this.transceivers[0].dtlsTransport;\n } else {\n var transports = this._createIceAndDtlsTransports();\n transceiver.iceTransport = transports.iceTransport;\n transceiver.dtlsTransport = transports.dtlsTransport;\n }\n if (!doNotAdd) {\n this.transceivers.push(transceiver);\n }\n return transceiver;\n };\n\n RTCPeerConnection.prototype.addTrack = function(track, stream) {\n if (this._isClosed) {\n throw makeError('InvalidStateError',\n 'Attempted to call addTrack on a closed peerconnection.');\n }\n\n var alreadyExists = this.transceivers.find(function(s) {\n return s.track === track;\n });\n\n if (alreadyExists) {\n throw makeError('InvalidAccessError', 'Track already exists.');\n }\n\n var transceiver;\n for (var i = 0; i < this.transceivers.length; i++) {\n if (!this.transceivers[i].track &&\n this.transceivers[i].kind === track.kind) {\n transceiver = this.transceivers[i];\n }\n }\n if (!transceiver) {\n transceiver = this._createTransceiver(track.kind);\n }\n\n this._maybeFireNegotiationNeeded();\n\n if (this.localStreams.indexOf(stream) === -1) {\n this.localStreams.push(stream);\n }\n\n transceiver.track = track;\n transceiver.stream = stream;\n transceiver.rtpSender = new window.RTCRtpSender(track,\n transceiver.dtlsTransport);\n return transceiver.rtpSender;\n };\n\n RTCPeerConnection.prototype.addStream = function(stream) {\n var pc = this;\n if (edgeVersion >= 15025) {\n stream.getTracks().forEach(function(track) {\n pc.addTrack(track, stream);\n });\n } else {\n // Clone is necessary for local demos mostly, attaching directly\n // to two different senders does not work (build 10547).\n // Fixed in 15025 (or earlier)\n var clonedStream = stream.clone();\n stream.getTracks().forEach(function(track, idx) {\n var clonedTrack = clonedStream.getTracks()[idx];\n track.addEventListener('enabled', function(event) {\n clonedTrack.enabled = event.enabled;\n });\n });\n clonedStream.getTracks().forEach(function(track) {\n pc.addTrack(track, clonedStream);\n });\n }\n };\n\n RTCPeerConnection.prototype.removeTrack = function(sender) {\n if (this._isClosed) {\n throw makeError('InvalidStateError',\n 'Attempted to call removeTrack on a closed peerconnection.');\n }\n\n if (!(sender instanceof window.RTCRtpSender)) {\n throw new TypeError('Argument 1 of RTCPeerConnection.removeTrack ' +\n 'does not implement interface RTCRtpSender.');\n }\n\n var transceiver = this.transceivers.find(function(t) {\n return t.rtpSender === sender;\n });\n\n if (!transceiver) {\n throw makeError('InvalidAccessError',\n 'Sender was not created by this connection.');\n }\n var stream = transceiver.stream;\n\n transceiver.rtpSender.stop();\n transceiver.rtpSender = null;\n transceiver.track = null;\n transceiver.stream = null;\n\n // remove the stream from the set of local streams\n var localStreams = this.transceivers.map(function(t) {\n return t.stream;\n });\n if (localStreams.indexOf(stream) === -1 &&\n this.localStreams.indexOf(stream) > -1) {\n this.localStreams.splice(this.localStreams.indexOf(stream), 1);\n }\n\n this._maybeFireNegotiationNeeded();\n };\n\n RTCPeerConnection.prototype.removeStream = function(stream) {\n var pc = this;\n stream.getTracks().forEach(function(track) {\n var sender = pc.getSenders().find(function(s) {\n return s.track === track;\n });\n if (sender) {\n pc.removeTrack(sender);\n }\n });\n };\n\n RTCPeerConnection.prototype.getSenders = function() {\n return this.transceivers.filter(function(transceiver) {\n return !!transceiver.rtpSender;\n })\n .map(function(transceiver) {\n return transceiver.rtpSender;\n });\n };\n\n RTCPeerConnection.prototype.getReceivers = function() {\n return this.transceivers.filter(function(transceiver) {\n return !!transceiver.rtpReceiver;\n })\n .map(function(transceiver) {\n return transceiver.rtpReceiver;\n });\n };\n\n\n RTCPeerConnection.prototype._createIceGatherer = function(sdpMLineIndex,\n usingBundle) {\n var pc = this;\n if (usingBundle && sdpMLineIndex > 0) {\n return this.transceivers[0].iceGatherer;\n } else if (this._iceGatherers.length) {\n return this._iceGatherers.shift();\n }\n var iceGatherer = new window.RTCIceGatherer({\n iceServers: this._config.iceServers,\n gatherPolicy: this._config.iceTransportPolicy\n });\n Object.defineProperty(iceGatherer, 'state',\n {value: 'new', writable: true}\n );\n\n this.transceivers[sdpMLineIndex].bufferedCandidateEvents = [];\n this.transceivers[sdpMLineIndex].bufferCandidates = function(event) {\n var end = !event.candidate || Object.keys(event.candidate).length === 0;\n // polyfill since RTCIceGatherer.state is not implemented in\n // Edge 10547 yet.\n iceGatherer.state = end ? 'completed' : 'gathering';\n if (pc.transceivers[sdpMLineIndex].bufferedCandidateEvents !== null) {\n pc.transceivers[sdpMLineIndex].bufferedCandidateEvents.push(event);\n }\n };\n iceGatherer.addEventListener('localcandidate',\n this.transceivers[sdpMLineIndex].bufferCandidates);\n return iceGatherer;\n };\n\n // start gathering from an RTCIceGatherer.\n RTCPeerConnection.prototype._gather = function(mid, sdpMLineIndex) {\n var pc = this;\n var iceGatherer = this.transceivers[sdpMLineIndex].iceGatherer;\n if (iceGatherer.onlocalcandidate) {\n return;\n }\n var bufferedCandidateEvents =\n this.transceivers[sdpMLineIndex].bufferedCandidateEvents;\n this.transceivers[sdpMLineIndex].bufferedCandidateEvents = null;\n iceGatherer.removeEventListener('localcandidate',\n this.transceivers[sdpMLineIndex].bufferCandidates);\n iceGatherer.onlocalcandidate = function(evt) {\n if (pc.usingBundle && sdpMLineIndex > 0) {\n // if we know that we use bundle we can drop candidates with\n // ѕdpMLineIndex > 0. If we don't do this then our state gets\n // confused since we dispose the extra ice gatherer.\n return;\n }\n var event = new Event('icecandidate');\n event.candidate = {sdpMid: mid, sdpMLineIndex: sdpMLineIndex};\n\n var cand = evt.candidate;\n // Edge emits an empty object for RTCIceCandidateComplete‥\n var end = !cand || Object.keys(cand).length === 0;\n if (end) {\n // polyfill since RTCIceGatherer.state is not implemented in\n // Edge 10547 yet.\n if (iceGatherer.state === 'new' || iceGatherer.state === 'gathering') {\n iceGatherer.state = 'completed';\n }\n } else {\n if (iceGatherer.state === 'new') {\n iceGatherer.state = 'gathering';\n }\n // RTCIceCandidate doesn't have a component, needs to be added\n cand.component = 1;\n // also the usernameFragment. TODO: update SDP to take both variants.\n cand.ufrag = iceGatherer.getLocalParameters().usernameFragment;\n\n var serializedCandidate = SDPUtils.writeCandidate(cand);\n event.candidate = Object.assign(event.candidate,\n SDPUtils.parseCandidate(serializedCandidate));\n\n event.candidate.candidate = serializedCandidate;\n event.candidate.toJSON = function() {\n return {\n candidate: event.candidate.candidate,\n sdpMid: event.candidate.sdpMid,\n sdpMLineIndex: event.candidate.sdpMLineIndex,\n usernameFragment: event.candidate.usernameFragment\n };\n };\n }\n\n // update local description.\n var sections = SDPUtils.getMediaSections(pc._localDescription.sdp);\n if (!end) {\n sections[event.candidate.sdpMLineIndex] +=\n 'a=' + event.candidate.candidate + '\\r\\n';\n } else {\n sections[event.candidate.sdpMLineIndex] +=\n 'a=end-of-candidates\\r\\n';\n }\n pc._localDescription.sdp =\n SDPUtils.getDescription(pc._localDescription.sdp) +\n sections.join('');\n var complete = pc.transceivers.every(function(transceiver) {\n return transceiver.iceGatherer &&\n transceiver.iceGatherer.state === 'completed';\n });\n\n if (pc.iceGatheringState !== 'gathering') {\n pc.iceGatheringState = 'gathering';\n pc._emitGatheringStateChange();\n }\n\n // Emit candidate. Also emit null candidate when all gatherers are\n // complete.\n if (!end) {\n pc._dispatchEvent('icecandidate', event);\n }\n if (complete) {\n pc._dispatchEvent('icecandidate', new Event('icecandidate'));\n pc.iceGatheringState = 'complete';\n pc._emitGatheringStateChange();\n }\n };\n\n // emit already gathered candidates.\n window.setTimeout(function() {\n bufferedCandidateEvents.forEach(function(e) {\n iceGatherer.onlocalcandidate(e);\n });\n }, 0);\n };\n\n // Create ICE transport and DTLS transport.\n RTCPeerConnection.prototype._createIceAndDtlsTransports = function() {\n var pc = this;\n var iceTransport = new window.RTCIceTransport(null);\n iceTransport.onicestatechange = function() {\n pc._updateIceConnectionState();\n pc._updateConnectionState();\n };\n\n var dtlsTransport = new window.RTCDtlsTransport(iceTransport);\n dtlsTransport.ondtlsstatechange = function() {\n pc._updateConnectionState();\n };\n dtlsTransport.onerror = function() {\n // onerror does not set state to failed by itself.\n Object.defineProperty(dtlsTransport, 'state',\n {value: 'failed', writable: true});\n pc._updateConnectionState();\n };\n\n return {\n iceTransport: iceTransport,\n dtlsTransport: dtlsTransport\n };\n };\n\n // Destroy ICE gatherer, ICE transport and DTLS transport.\n // Without triggering the callbacks.\n RTCPeerConnection.prototype._disposeIceAndDtlsTransports = function(\n sdpMLineIndex) {\n var iceGatherer = this.transceivers[sdpMLineIndex].iceGatherer;\n if (iceGatherer) {\n delete iceGatherer.onlocalcandidate;\n delete this.transceivers[sdpMLineIndex].iceGatherer;\n }\n var iceTransport = this.transceivers[sdpMLineIndex].iceTransport;\n if (iceTransport) {\n delete iceTransport.onicestatechange;\n delete this.transceivers[sdpMLineIndex].iceTransport;\n }\n var dtlsTransport = this.transceivers[sdpMLineIndex].dtlsTransport;\n if (dtlsTransport) {\n delete dtlsTransport.ondtlsstatechange;\n delete dtlsTransport.onerror;\n delete this.transceivers[sdpMLineIndex].dtlsTransport;\n }\n };\n\n // Start the RTP Sender and Receiver for a transceiver.\n RTCPeerConnection.prototype._transceive = function(transceiver,\n send, recv) {\n var params = getCommonCapabilities(transceiver.localCapabilities,\n transceiver.remoteCapabilities);\n if (send && transceiver.rtpSender) {\n params.encodings = transceiver.sendEncodingParameters;\n params.rtcp = {\n cname: SDPUtils.localCName,\n compound: transceiver.rtcpParameters.compound\n };\n if (transceiver.recvEncodingParameters.length) {\n params.rtcp.ssrc = transceiver.recvEncodingParameters[0].ssrc;\n }\n transceiver.rtpSender.send(params);\n }\n if (recv && transceiver.rtpReceiver && params.codecs.length > 0) {\n // remove RTX field in Edge 14942\n if (transceiver.kind === 'video'\n && transceiver.recvEncodingParameters\n && edgeVersion < 15019) {\n transceiver.recvEncodingParameters.forEach(function(p) {\n delete p.rtx;\n });\n }\n if (transceiver.recvEncodingParameters.length) {\n params.encodings = transceiver.recvEncodingParameters;\n } else {\n params.encodings = [{}];\n }\n params.rtcp = {\n compound: transceiver.rtcpParameters.compound\n };\n if (transceiver.rtcpParameters.cname) {\n params.rtcp.cname = transceiver.rtcpParameters.cname;\n }\n if (transceiver.sendEncodingParameters.length) {\n params.rtcp.ssrc = transceiver.sendEncodingParameters[0].ssrc;\n }\n transceiver.rtpReceiver.receive(params);\n }\n };\n\n RTCPeerConnection.prototype.setLocalDescription = function(description) {\n var pc = this;\n\n // Note: pranswer is not supported.\n if (['offer', 'answer'].indexOf(description.type) === -1) {\n return Promise.reject(makeError('TypeError',\n 'Unsupported type \"' + description.type + '\"'));\n }\n\n if (!isActionAllowedInSignalingState('setLocalDescription',\n description.type, pc.signalingState) || pc._isClosed) {\n return Promise.reject(makeError('InvalidStateError',\n 'Can not set local ' + description.type +\n ' in state ' + pc.signalingState));\n }\n\n var sections;\n var sessionpart;\n if (description.type === 'offer') {\n // VERY limited support for SDP munging. Limited to:\n // * changing the order of codecs\n sections = SDPUtils.splitSections(description.sdp);\n sessionpart = sections.shift();\n sections.forEach(function(mediaSection, sdpMLineIndex) {\n var caps = SDPUtils.parseRtpParameters(mediaSection);\n pc.transceivers[sdpMLineIndex].localCapabilities = caps;\n });\n\n pc.transceivers.forEach(function(transceiver, sdpMLineIndex) {\n pc._gather(transceiver.mid, sdpMLineIndex);\n });\n } else if (description.type === 'answer') {\n sections = SDPUtils.splitSections(pc._remoteDescription.sdp);\n sessionpart = sections.shift();\n var isIceLite = SDPUtils.matchPrefix(sessionpart,\n 'a=ice-lite').length > 0;\n sections.forEach(function(mediaSection, sdpMLineIndex) {\n var transceiver = pc.transceivers[sdpMLineIndex];\n var iceGatherer = transceiver.iceGatherer;\n var iceTransport = transceiver.iceTransport;\n var dtlsTransport = transceiver.dtlsTransport;\n var localCapabilities = transceiver.localCapabilities;\n var remoteCapabilities = transceiver.remoteCapabilities;\n\n // treat bundle-only as not-rejected.\n var rejected = SDPUtils.isRejected(mediaSection) &&\n SDPUtils.matchPrefix(mediaSection, 'a=bundle-only').length === 0;\n\n if (!rejected && !transceiver.rejected) {\n var remoteIceParameters = SDPUtils.getIceParameters(\n mediaSection, sessionpart);\n var remoteDtlsParameters = SDPUtils.getDtlsParameters(\n mediaSection, sessionpart);\n if (isIceLite) {\n remoteDtlsParameters.role = 'server';\n }\n\n if (!pc.usingBundle || sdpMLineIndex === 0) {\n pc._gather(transceiver.mid, sdpMLineIndex);\n if (iceTransport.state === 'new') {\n iceTransport.start(iceGatherer, remoteIceParameters,\n isIceLite ? 'controlling' : 'controlled');\n }\n if (dtlsTransport.state === 'new') {\n dtlsTransport.start(remoteDtlsParameters);\n }\n }\n\n // Calculate intersection of capabilities.\n var params = getCommonCapabilities(localCapabilities,\n remoteCapabilities);\n\n // Start the RTCRtpSender. The RTCRtpReceiver for this\n // transceiver has already been started in setRemoteDescription.\n pc._transceive(transceiver,\n params.codecs.length > 0,\n false);\n }\n });\n }\n\n pc._localDescription = {\n type: description.type,\n sdp: description.sdp\n };\n if (description.type === 'offer') {\n pc._updateSignalingState('have-local-offer');\n } else {\n pc._updateSignalingState('stable');\n }\n\n return Promise.resolve();\n };\n\n RTCPeerConnection.prototype.setRemoteDescription = function(description) {\n var pc = this;\n\n // Note: pranswer is not supported.\n if (['offer', 'answer'].indexOf(description.type) === -1) {\n return Promise.reject(makeError('TypeError',\n 'Unsupported type \"' + description.type + '\"'));\n }\n\n if (!isActionAllowedInSignalingState('setRemoteDescription',\n description.type, pc.signalingState) || pc._isClosed) {\n return Promise.reject(makeError('InvalidStateError',\n 'Can not set remote ' + description.type +\n ' in state ' + pc.signalingState));\n }\n\n var streams = {};\n pc.remoteStreams.forEach(function(stream) {\n streams[stream.id] = stream;\n });\n var receiverList = [];\n var sections = SDPUtils.splitSections(description.sdp);\n var sessionpart = sections.shift();\n var isIceLite = SDPUtils.matchPrefix(sessionpart,\n 'a=ice-lite').length > 0;\n var usingBundle = SDPUtils.matchPrefix(sessionpart,\n 'a=group:BUNDLE ').length > 0;\n pc.usingBundle = usingBundle;\n var iceOptions = SDPUtils.matchPrefix(sessionpart,\n 'a=ice-options:')[0];\n if (iceOptions) {\n pc.canTrickleIceCandidates = iceOptions.substr(14).split(' ')\n .indexOf('trickle') >= 0;\n } else {\n pc.canTrickleIceCandidates = false;\n }\n\n sections.forEach(function(mediaSection, sdpMLineIndex) {\n var lines = SDPUtils.splitLines(mediaSection);\n var kind = SDPUtils.getKind(mediaSection);\n // treat bundle-only as not-rejected.\n var rejected = SDPUtils.isRejected(mediaSection) &&\n SDPUtils.matchPrefix(mediaSection, 'a=bundle-only').length === 0;\n var protocol = lines[0].substr(2).split(' ')[2];\n\n var direction = SDPUtils.getDirection(mediaSection, sessionpart);\n var remoteMsid = SDPUtils.parseMsid(mediaSection);\n\n var mid = SDPUtils.getMid(mediaSection) || SDPUtils.generateIdentifier();\n\n // Reject datachannels which are not implemented yet.\n if (rejected || (kind === 'application' && (protocol === 'DTLS/SCTP' ||\n protocol === 'UDP/DTLS/SCTP'))) {\n // TODO: this is dangerous in the case where a non-rejected m-line\n // becomes rejected.\n pc.transceivers[sdpMLineIndex] = {\n mid: mid,\n kind: kind,\n protocol: protocol,\n rejected: true\n };\n return;\n }\n\n if (!rejected && pc.transceivers[sdpMLineIndex] &&\n pc.transceivers[sdpMLineIndex].rejected) {\n // recycle a rejected transceiver.\n pc.transceivers[sdpMLineIndex] = pc._createTransceiver(kind, true);\n }\n\n var transceiver;\n var iceGatherer;\n var iceTransport;\n var dtlsTransport;\n var rtpReceiver;\n var sendEncodingParameters;\n var recvEncodingParameters;\n var localCapabilities;\n\n var track;\n // FIXME: ensure the mediaSection has rtcp-mux set.\n var remoteCapabilities = SDPUtils.parseRtpParameters(mediaSection);\n var remoteIceParameters;\n var remoteDtlsParameters;\n if (!rejected) {\n remoteIceParameters = SDPUtils.getIceParameters(mediaSection,\n sessionpart);\n remoteDtlsParameters = SDPUtils.getDtlsParameters(mediaSection,\n sessionpart);\n remoteDtlsParameters.role = 'client';\n }\n recvEncodingParameters =\n SDPUtils.parseRtpEncodingParameters(mediaSection);\n\n var rtcpParameters = SDPUtils.parseRtcpParameters(mediaSection);\n\n var isComplete = SDPUtils.matchPrefix(mediaSection,\n 'a=end-of-candidates', sessionpart).length > 0;\n var cands = SDPUtils.matchPrefix(mediaSection, 'a=candidate:')\n .map(function(cand) {\n return SDPUtils.parseCandidate(cand);\n })\n .filter(function(cand) {\n return cand.component === 1;\n });\n\n // Check if we can use BUNDLE and dispose transports.\n if ((description.type === 'offer' || description.type === 'answer') &&\n !rejected && usingBundle && sdpMLineIndex > 0 &&\n pc.transceivers[sdpMLineIndex]) {\n pc._disposeIceAndDtlsTransports(sdpMLineIndex);\n pc.transceivers[sdpMLineIndex].iceGatherer =\n pc.transceivers[0].iceGatherer;\n pc.transceivers[sdpMLineIndex].iceTransport =\n pc.transceivers[0].iceTransport;\n pc.transceivers[sdpMLineIndex].dtlsTransport =\n pc.transceivers[0].dtlsTransport;\n if (pc.transceivers[sdpMLineIndex].rtpSender) {\n pc.transceivers[sdpMLineIndex].rtpSender.setTransport(\n pc.transceivers[0].dtlsTransport);\n }\n if (pc.transceivers[sdpMLineIndex].rtpReceiver) {\n pc.transceivers[sdpMLineIndex].rtpReceiver.setTransport(\n pc.transceivers[0].dtlsTransport);\n }\n }\n if (description.type === 'offer' && !rejected) {\n transceiver = pc.transceivers[sdpMLineIndex] ||\n pc._createTransceiver(kind);\n transceiver.mid = mid;\n\n if (!transceiver.iceGatherer) {\n transceiver.iceGatherer = pc._createIceGatherer(sdpMLineIndex,\n usingBundle);\n }\n\n if (cands.length && transceiver.iceTransport.state === 'new') {\n if (isComplete && (!usingBundle || sdpMLineIndex === 0)) {\n transceiver.iceTransport.setRemoteCandidates(cands);\n } else {\n cands.forEach(function(candidate) {\n maybeAddCandidate(transceiver.iceTransport, candidate);\n });\n }\n }\n\n localCapabilities = window.RTCRtpReceiver.getCapabilities(kind);\n\n // filter RTX until additional stuff needed for RTX is implemented\n // in adapter.js\n if (edgeVersion < 15019) {\n localCapabilities.codecs = localCapabilities.codecs.filter(\n function(codec) {\n return codec.name !== 'rtx';\n });\n }\n\n sendEncodingParameters = transceiver.sendEncodingParameters || [{\n ssrc: (2 * sdpMLineIndex + 2) * 1001\n }];\n\n // TODO: rewrite to use http://w3c.github.io/webrtc-pc/#set-associated-remote-streams\n var isNewTrack = false;\n if (direction === 'sendrecv' || direction === 'sendonly') {\n isNewTrack = !transceiver.rtpReceiver;\n rtpReceiver = transceiver.rtpReceiver ||\n new window.RTCRtpReceiver(transceiver.dtlsTransport, kind);\n\n if (isNewTrack) {\n var stream;\n track = rtpReceiver.track;\n // FIXME: does not work with Plan B.\n if (remoteMsid && remoteMsid.stream === '-') {\n // no-op. a stream id of '-' means: no associated stream.\n } else if (remoteMsid) {\n if (!streams[remoteMsid.stream]) {\n streams[remoteMsid.stream] = new window.MediaStream();\n Object.defineProperty(streams[remoteMsid.stream], 'id', {\n get: function() {\n return remoteMsid.stream;\n }\n });\n }\n Object.defineProperty(track, 'id', {\n get: function() {\n return remoteMsid.track;\n }\n });\n stream = streams[remoteMsid.stream];\n } else {\n if (!streams.default) {\n streams.default = new window.MediaStream();\n }\n stream = streams.default;\n }\n if (stream) {\n addTrackToStreamAndFireEvent(track, stream);\n transceiver.associatedRemoteMediaStreams.push(stream);\n }\n receiverList.push([track, rtpReceiver, stream]);\n }\n } else if (transceiver.rtpReceiver && transceiver.rtpReceiver.track) {\n transceiver.associatedRemoteMediaStreams.forEach(function(s) {\n var nativeTrack = s.getTracks().find(function(t) {\n return t.id === transceiver.rtpReceiver.track.id;\n });\n if (nativeTrack) {\n removeTrackFromStreamAndFireEvent(nativeTrack, s);\n }\n });\n transceiver.associatedRemoteMediaStreams = [];\n }\n\n transceiver.localCapabilities = localCapabilities;\n transceiver.remoteCapabilities = remoteCapabilities;\n transceiver.rtpReceiver = rtpReceiver;\n transceiver.rtcpParameters = rtcpParameters;\n transceiver.sendEncodingParameters = sendEncodingParameters;\n transceiver.recvEncodingParameters = recvEncodingParameters;\n\n // Start the RTCRtpReceiver now. The RTPSender is started in\n // setLocalDescription.\n pc._transceive(pc.transceivers[sdpMLineIndex],\n false,\n isNewTrack);\n } else if (description.type === 'answer' && !rejected) {\n transceiver = pc.transceivers[sdpMLineIndex];\n iceGatherer = transceiver.iceGatherer;\n iceTransport = transceiver.iceTransport;\n dtlsTransport = transceiver.dtlsTransport;\n rtpReceiver = transceiver.rtpReceiver;\n sendEncodingParameters = transceiver.sendEncodingParameters;\n localCapabilities = transceiver.localCapabilities;\n\n pc.transceivers[sdpMLineIndex].recvEncodingParameters =\n recvEncodingParameters;\n pc.transceivers[sdpMLineIndex].remoteCapabilities =\n remoteCapabilities;\n pc.transceivers[sdpMLineIndex].rtcpParameters = rtcpParameters;\n\n if (cands.length && iceTransport.state === 'new') {\n if ((isIceLite || isComplete) &&\n (!usingBundle || sdpMLineIndex === 0)) {\n iceTransport.setRemoteCandidates(cands);\n } else {\n cands.forEach(function(candidate) {\n maybeAddCandidate(transceiver.iceTransport, candidate);\n });\n }\n }\n\n if (!usingBundle || sdpMLineIndex === 0) {\n if (iceTransport.state === 'new') {\n iceTransport.start(iceGatherer, remoteIceParameters,\n 'controlling');\n }\n if (dtlsTransport.state === 'new') {\n dtlsTransport.start(remoteDtlsParameters);\n }\n }\n\n // If the offer contained RTX but the answer did not,\n // remove RTX from sendEncodingParameters.\n var commonCapabilities = getCommonCapabilities(\n transceiver.localCapabilities,\n transceiver.remoteCapabilities);\n\n var hasRtx = commonCapabilities.codecs.filter(function(c) {\n return c.name.toLowerCase() === 'rtx';\n }).length;\n if (!hasRtx && transceiver.sendEncodingParameters[0].rtx) {\n delete transceiver.sendEncodingParameters[0].rtx;\n }\n\n pc._transceive(transceiver,\n direction === 'sendrecv' || direction === 'recvonly',\n direction === 'sendrecv' || direction === 'sendonly');\n\n // TODO: rewrite to use http://w3c.github.io/webrtc-pc/#set-associated-remote-streams\n if (rtpReceiver &&\n (direction === 'sendrecv' || direction === 'sendonly')) {\n track = rtpReceiver.track;\n if (remoteMsid) {\n if (!streams[remoteMsid.stream]) {\n streams[remoteMsid.stream] = new window.MediaStream();\n }\n addTrackToStreamAndFireEvent(track, streams[remoteMsid.stream]);\n receiverList.push([track, rtpReceiver, streams[remoteMsid.stream]]);\n } else {\n if (!streams.default) {\n streams.default = new window.MediaStream();\n }\n addTrackToStreamAndFireEvent(track, streams.default);\n receiverList.push([track, rtpReceiver, streams.default]);\n }\n } else {\n // FIXME: actually the receiver should be created later.\n delete transceiver.rtpReceiver;\n }\n }\n });\n\n if (pc._dtlsRole === undefined) {\n pc._dtlsRole = description.type === 'offer' ? 'active' : 'passive';\n }\n\n pc._remoteDescription = {\n type: description.type,\n sdp: description.sdp\n };\n if (description.type === 'offer') {\n pc._updateSignalingState('have-remote-offer');\n } else {\n pc._updateSignalingState('stable');\n }\n Object.keys(streams).forEach(function(sid) {\n var stream = streams[sid];\n if (stream.getTracks().length) {\n if (pc.remoteStreams.indexOf(stream) === -1) {\n pc.remoteStreams.push(stream);\n var event = new Event('addstream');\n event.stream = stream;\n window.setTimeout(function() {\n pc._dispatchEvent('addstream', event);\n });\n }\n\n receiverList.forEach(function(item) {\n var track = item[0];\n var receiver = item[1];\n if (stream.id !== item[2].id) {\n return;\n }\n fireAddTrack(pc, track, receiver, [stream]);\n });\n }\n });\n receiverList.forEach(function(item) {\n if (item[2]) {\n return;\n }\n fireAddTrack(pc, item[0], item[1], []);\n });\n\n // check whether addIceCandidate({}) was called within four seconds after\n // setRemoteDescription.\n window.setTimeout(function() {\n if (!(pc && pc.transceivers)) {\n return;\n }\n pc.transceivers.forEach(function(transceiver) {\n if (transceiver.iceTransport &&\n transceiver.iceTransport.state === 'new' &&\n transceiver.iceTransport.getRemoteCandidates().length > 0) {\n console.warn('Timeout for addRemoteCandidate. Consider sending ' +\n 'an end-of-candidates notification');\n transceiver.iceTransport.addRemoteCandidate({});\n }\n });\n }, 4000);\n\n return Promise.resolve();\n };\n\n RTCPeerConnection.prototype.close = function() {\n this.transceivers.forEach(function(transceiver) {\n /* not yet\n if (transceiver.iceGatherer) {\n transceiver.iceGatherer.close();\n }\n */\n if (transceiver.iceTransport) {\n transceiver.iceTransport.stop();\n }\n if (transceiver.dtlsTransport) {\n transceiver.dtlsTransport.stop();\n }\n if (transceiver.rtpSender) {\n transceiver.rtpSender.stop();\n }\n if (transceiver.rtpReceiver) {\n transceiver.rtpReceiver.stop();\n }\n });\n // FIXME: clean up tracks, local streams, remote streams, etc\n this._isClosed = true;\n this._updateSignalingState('closed');\n };\n\n // Update the signaling state.\n RTCPeerConnection.prototype._updateSignalingState = function(newState) {\n this.signalingState = newState;\n var event = new Event('signalingstatechange');\n this._dispatchEvent('signalingstatechange', event);\n };\n\n // Determine whether to fire the negotiationneeded event.\n RTCPeerConnection.prototype._maybeFireNegotiationNeeded = function() {\n var pc = this;\n if (this.signalingState !== 'stable' || this.needNegotiation === true) {\n return;\n }\n this.needNegotiation = true;\n window.setTimeout(function() {\n if (pc.needNegotiation) {\n pc.needNegotiation = false;\n var event = new Event('negotiationneeded');\n pc._dispatchEvent('negotiationneeded', event);\n }\n }, 0);\n };\n\n // Update the ice connection state.\n RTCPeerConnection.prototype._updateIceConnectionState = function() {\n var newState;\n var states = {\n 'new': 0,\n closed: 0,\n checking: 0,\n connected: 0,\n completed: 0,\n disconnected: 0,\n failed: 0\n };\n this.transceivers.forEach(function(transceiver) {\n if (transceiver.iceTransport && !transceiver.rejected) {\n states[transceiver.iceTransport.state]++;\n }\n });\n\n newState = 'new';\n if (states.failed > 0) {\n newState = 'failed';\n } else if (states.checking > 0) {\n newState = 'checking';\n } else if (states.disconnected > 0) {\n newState = 'disconnected';\n } else if (states.new > 0) {\n newState = 'new';\n } else if (states.connected > 0) {\n newState = 'connected';\n } else if (states.completed > 0) {\n newState = 'completed';\n }\n\n if (newState !== this.iceConnectionState) {\n this.iceConnectionState = newState;\n var event = new Event('iceconnectionstatechange');\n this._dispatchEvent('iceconnectionstatechange', event);\n }\n };\n\n // Update the connection state.\n RTCPeerConnection.prototype._updateConnectionState = function() {\n var newState;\n var states = {\n 'new': 0,\n closed: 0,\n connecting: 0,\n connected: 0,\n completed: 0,\n disconnected: 0,\n failed: 0\n };\n this.transceivers.forEach(function(transceiver) {\n if (transceiver.iceTransport && transceiver.dtlsTransport &&\n !transceiver.rejected) {\n states[transceiver.iceTransport.state]++;\n states[transceiver.dtlsTransport.state]++;\n }\n });\n // ICETransport.completed and connected are the same for this purpose.\n states.connected += states.completed;\n\n newState = 'new';\n if (states.failed > 0) {\n newState = 'failed';\n } else if (states.connecting > 0) {\n newState = 'connecting';\n } else if (states.disconnected > 0) {\n newState = 'disconnected';\n } else if (states.new > 0) {\n newState = 'new';\n } else if (states.connected > 0) {\n newState = 'connected';\n }\n\n if (newState !== this.connectionState) {\n this.connectionState = newState;\n var event = new Event('connectionstatechange');\n this._dispatchEvent('connectionstatechange', event);\n }\n };\n\n RTCPeerConnection.prototype.createOffer = function() {\n var pc = this;\n\n if (pc._isClosed) {\n return Promise.reject(makeError('InvalidStateError',\n 'Can not call createOffer after close'));\n }\n\n var numAudioTracks = pc.transceivers.filter(function(t) {\n return t.kind === 'audio';\n }).length;\n var numVideoTracks = pc.transceivers.filter(function(t) {\n return t.kind === 'video';\n }).length;\n\n // Determine number of audio and video tracks we need to send/recv.\n var offerOptions = arguments[0];\n if (offerOptions) {\n // Reject Chrome legacy constraints.\n if (offerOptions.mandatory || offerOptions.optional) {\n throw new TypeError(\n 'Legacy mandatory/optional constraints not supported.');\n }\n if (offerOptions.offerToReceiveAudio !== undefined) {\n if (offerOptions.offerToReceiveAudio === true) {\n numAudioTracks = 1;\n } else if (offerOptions.offerToReceiveAudio === false) {\n numAudioTracks = 0;\n } else {\n numAudioTracks = offerOptions.offerToReceiveAudio;\n }\n }\n if (offerOptions.offerToReceiveVideo !== undefined) {\n if (offerOptions.offerToReceiveVideo === true) {\n numVideoTracks = 1;\n } else if (offerOptions.offerToReceiveVideo === false) {\n numVideoTracks = 0;\n } else {\n numVideoTracks = offerOptions.offerToReceiveVideo;\n }\n }\n }\n\n pc.transceivers.forEach(function(transceiver) {\n if (transceiver.kind === 'audio') {\n numAudioTracks--;\n if (numAudioTracks < 0) {\n transceiver.wantReceive = false;\n }\n } else if (transceiver.kind === 'video') {\n numVideoTracks--;\n if (numVideoTracks < 0) {\n transceiver.wantReceive = false;\n }\n }\n });\n\n // Create M-lines for recvonly streams.\n while (numAudioTracks > 0 || numVideoTracks > 0) {\n if (numAudioTracks > 0) {\n pc._createTransceiver('audio');\n numAudioTracks--;\n }\n if (numVideoTracks > 0) {\n pc._createTransceiver('video');\n numVideoTracks--;\n }\n }\n\n var sdp = SDPUtils.writeSessionBoilerplate(pc._sdpSessionId,\n pc._sdpSessionVersion++);\n pc.transceivers.forEach(function(transceiver, sdpMLineIndex) {\n // For each track, create an ice gatherer, ice transport,\n // dtls transport, potentially rtpsender and rtpreceiver.\n var track = transceiver.track;\n var kind = transceiver.kind;\n var mid = transceiver.mid || SDPUtils.generateIdentifier();\n transceiver.mid = mid;\n\n if (!transceiver.iceGatherer) {\n transceiver.iceGatherer = pc._createIceGatherer(sdpMLineIndex,\n pc.usingBundle);\n }\n\n var localCapabilities = window.RTCRtpSender.getCapabilities(kind);\n // filter RTX until additional stuff needed for RTX is implemented\n // in adapter.js\n if (edgeVersion < 15019) {\n localCapabilities.codecs = localCapabilities.codecs.filter(\n function(codec) {\n return codec.name !== 'rtx';\n });\n }\n localCapabilities.codecs.forEach(function(codec) {\n // work around https://bugs.chromium.org/p/webrtc/issues/detail?id=6552\n // by adding level-asymmetry-allowed=1\n if (codec.name === 'H264' &&\n codec.parameters['level-asymmetry-allowed'] === undefined) {\n codec.parameters['level-asymmetry-allowed'] = '1';\n }\n\n // for subsequent offers, we might have to re-use the payload\n // type of the last offer.\n if (transceiver.remoteCapabilities &&\n transceiver.remoteCapabilities.codecs) {\n transceiver.remoteCapabilities.codecs.forEach(function(remoteCodec) {\n if (codec.name.toLowerCase() === remoteCodec.name.toLowerCase() &&\n codec.clockRate === remoteCodec.clockRate) {\n codec.preferredPayloadType = remoteCodec.payloadType;\n }\n });\n }\n });\n localCapabilities.headerExtensions.forEach(function(hdrExt) {\n var remoteExtensions = transceiver.remoteCapabilities &&\n transceiver.remoteCapabilities.headerExtensions || [];\n remoteExtensions.forEach(function(rHdrExt) {\n if (hdrExt.uri === rHdrExt.uri) {\n hdrExt.id = rHdrExt.id;\n }\n });\n });\n\n // generate an ssrc now, to be used later in rtpSender.send\n var sendEncodingParameters = transceiver.sendEncodingParameters || [{\n ssrc: (2 * sdpMLineIndex + 1) * 1001\n }];\n if (track) {\n // add RTX\n if (edgeVersion >= 15019 && kind === 'video' &&\n !sendEncodingParameters[0].rtx) {\n sendEncodingParameters[0].rtx = {\n ssrc: sendEncodingParameters[0].ssrc + 1\n };\n }\n }\n\n if (transceiver.wantReceive) {\n transceiver.rtpReceiver = new window.RTCRtpReceiver(\n transceiver.dtlsTransport, kind);\n }\n\n transceiver.localCapabilities = localCapabilities;\n transceiver.sendEncodingParameters = sendEncodingParameters;\n });\n\n // always offer BUNDLE and dispose on return if not supported.\n if (pc._config.bundlePolicy !== 'max-compat') {\n sdp += 'a=group:BUNDLE ' + pc.transceivers.map(function(t) {\n return t.mid;\n }).join(' ') + '\\r\\n';\n }\n sdp += 'a=ice-options:trickle\\r\\n';\n\n pc.transceivers.forEach(function(transceiver, sdpMLineIndex) {\n sdp += writeMediaSection(transceiver, transceiver.localCapabilities,\n 'offer', transceiver.stream, pc._dtlsRole);\n sdp += 'a=rtcp-rsize\\r\\n';\n\n if (transceiver.iceGatherer && pc.iceGatheringState !== 'new' &&\n (sdpMLineIndex === 0 || !pc.usingBundle)) {\n transceiver.iceGatherer.getLocalCandidates().forEach(function(cand) {\n cand.component = 1;\n sdp += 'a=' + SDPUtils.writeCandidate(cand) + '\\r\\n';\n });\n\n if (transceiver.iceGatherer.state === 'completed') {\n sdp += 'a=end-of-candidates\\r\\n';\n }\n }\n });\n\n var desc = new window.RTCSessionDescription({\n type: 'offer',\n sdp: sdp\n });\n return Promise.resolve(desc);\n };\n\n RTCPeerConnection.prototype.createAnswer = function() {\n var pc = this;\n\n if (pc._isClosed) {\n return Promise.reject(makeError('InvalidStateError',\n 'Can not call createAnswer after close'));\n }\n\n if (!(pc.signalingState === 'have-remote-offer' ||\n pc.signalingState === 'have-local-pranswer')) {\n return Promise.reject(makeError('InvalidStateError',\n 'Can not call createAnswer in signalingState ' + pc.signalingState));\n }\n\n var sdp = SDPUtils.writeSessionBoilerplate(pc._sdpSessionId,\n pc._sdpSessionVersion++);\n if (pc.usingBundle) {\n sdp += 'a=group:BUNDLE ' + pc.transceivers.map(function(t) {\n return t.mid;\n }).join(' ') + '\\r\\n';\n }\n sdp += 'a=ice-options:trickle\\r\\n';\n\n var mediaSectionsInOffer = SDPUtils.getMediaSections(\n pc._remoteDescription.sdp).length;\n pc.transceivers.forEach(function(transceiver, sdpMLineIndex) {\n if (sdpMLineIndex + 1 > mediaSectionsInOffer) {\n return;\n }\n if (transceiver.rejected) {\n if (transceiver.kind === 'application') {\n if (transceiver.protocol === 'DTLS/SCTP') { // legacy fmt\n sdp += 'm=application 0 DTLS/SCTP 5000\\r\\n';\n } else {\n sdp += 'm=application 0 ' + transceiver.protocol +\n ' webrtc-datachannel\\r\\n';\n }\n } else if (transceiver.kind === 'audio') {\n sdp += 'm=audio 0 UDP/TLS/RTP/SAVPF 0\\r\\n' +\n 'a=rtpmap:0 PCMU/8000\\r\\n';\n } else if (transceiver.kind === 'video') {\n sdp += 'm=video 0 UDP/TLS/RTP/SAVPF 120\\r\\n' +\n 'a=rtpmap:120 VP8/90000\\r\\n';\n }\n sdp += 'c=IN IP4 0.0.0.0\\r\\n' +\n 'a=inactive\\r\\n' +\n 'a=mid:' + transceiver.mid + '\\r\\n';\n return;\n }\n\n // FIXME: look at direction.\n if (transceiver.stream) {\n var localTrack;\n if (transceiver.kind === 'audio') {\n localTrack = transceiver.stream.getAudioTracks()[0];\n } else if (transceiver.kind === 'video') {\n localTrack = transceiver.stream.getVideoTracks()[0];\n }\n if (localTrack) {\n // add RTX\n if (edgeVersion >= 15019 && transceiver.kind === 'video' &&\n !transceiver.sendEncodingParameters[0].rtx) {\n transceiver.sendEncodingParameters[0].rtx = {\n ssrc: transceiver.sendEncodingParameters[0].ssrc + 1\n };\n }\n }\n }\n\n // Calculate intersection of capabilities.\n var commonCapabilities = getCommonCapabilities(\n transceiver.localCapabilities,\n transceiver.remoteCapabilities);\n\n var hasRtx = commonCapabilities.codecs.filter(function(c) {\n return c.name.toLowerCase() === 'rtx';\n }).length;\n if (!hasRtx && transceiver.sendEncodingParameters[0].rtx) {\n delete transceiver.sendEncodingParameters[0].rtx;\n }\n\n sdp += writeMediaSection(transceiver, commonCapabilities,\n 'answer', transceiver.stream, pc._dtlsRole);\n if (transceiver.rtcpParameters &&\n transceiver.rtcpParameters.reducedSize) {\n sdp += 'a=rtcp-rsize\\r\\n';\n }\n });\n\n var desc = new window.RTCSessionDescription({\n type: 'answer',\n sdp: sdp\n });\n return Promise.resolve(desc);\n };\n\n RTCPeerConnection.prototype.addIceCandidate = function(candidate) {\n var pc = this;\n var sections;\n if (candidate && !(candidate.sdpMLineIndex !== undefined ||\n candidate.sdpMid)) {\n return Promise.reject(new TypeError('sdpMLineIndex or sdpMid required'));\n }\n\n // TODO: needs to go into ops queue.\n return new Promise(function(resolve, reject) {\n if (!pc._remoteDescription) {\n return reject(makeError('InvalidStateError',\n 'Can not add ICE candidate without a remote description'));\n } else if (!candidate || candidate.candidate === '') {\n for (var j = 0; j < pc.transceivers.length; j++) {\n if (pc.transceivers[j].rejected) {\n continue;\n }\n pc.transceivers[j].iceTransport.addRemoteCandidate({});\n sections = SDPUtils.getMediaSections(pc._remoteDescription.sdp);\n sections[j] += 'a=end-of-candidates\\r\\n';\n pc._remoteDescription.sdp =\n SDPUtils.getDescription(pc._remoteDescription.sdp) +\n sections.join('');\n if (pc.usingBundle) {\n break;\n }\n }\n } else {\n var sdpMLineIndex = candidate.sdpMLineIndex;\n if (candidate.sdpMid) {\n for (var i = 0; i < pc.transceivers.length; i++) {\n if (pc.transceivers[i].mid === candidate.sdpMid) {\n sdpMLineIndex = i;\n break;\n }\n }\n }\n var transceiver = pc.transceivers[sdpMLineIndex];\n if (transceiver) {\n if (transceiver.rejected) {\n return resolve();\n }\n var cand = Object.keys(candidate.candidate).length > 0 ?\n SDPUtils.parseCandidate(candidate.candidate) : {};\n // Ignore Chrome's invalid candidates since Edge does not like them.\n if (cand.protocol === 'tcp' && (cand.port === 0 || cand.port === 9)) {\n return resolve();\n }\n // Ignore RTCP candidates, we assume RTCP-MUX.\n if (cand.component && cand.component !== 1) {\n return resolve();\n }\n // when using bundle, avoid adding candidates to the wrong\n // ice transport. And avoid adding candidates added in the SDP.\n if (sdpMLineIndex === 0 || (sdpMLineIndex > 0 &&\n transceiver.iceTransport !== pc.transceivers[0].iceTransport)) {\n if (!maybeAddCandidate(transceiver.iceTransport, cand)) {\n return reject(makeError('OperationError',\n 'Can not add ICE candidate'));\n }\n }\n\n // update the remoteDescription.\n var candidateString = candidate.candidate.trim();\n if (candidateString.indexOf('a=') === 0) {\n candidateString = candidateString.substr(2);\n }\n sections = SDPUtils.getMediaSections(pc._remoteDescription.sdp);\n sections[sdpMLineIndex] += 'a=' +\n (cand.type ? candidateString : 'end-of-candidates')\n + '\\r\\n';\n pc._remoteDescription.sdp =\n SDPUtils.getDescription(pc._remoteDescription.sdp) +\n sections.join('');\n } else {\n return reject(makeError('OperationError',\n 'Can not add ICE candidate'));\n }\n }\n resolve();\n });\n };\n\n RTCPeerConnection.prototype.getStats = function(selector) {\n if (selector && selector instanceof window.MediaStreamTrack) {\n var senderOrReceiver = null;\n this.transceivers.forEach(function(transceiver) {\n if (transceiver.rtpSender &&\n transceiver.rtpSender.track === selector) {\n senderOrReceiver = transceiver.rtpSender;\n } else if (transceiver.rtpReceiver &&\n transceiver.rtpReceiver.track === selector) {\n senderOrReceiver = transceiver.rtpReceiver;\n }\n });\n if (!senderOrReceiver) {\n throw makeError('InvalidAccessError', 'Invalid selector.');\n }\n return senderOrReceiver.getStats();\n }\n\n var promises = [];\n this.transceivers.forEach(function(transceiver) {\n ['rtpSender', 'rtpReceiver', 'iceGatherer', 'iceTransport',\n 'dtlsTransport'].forEach(function(method) {\n if (transceiver[method]) {\n promises.push(transceiver[method].getStats());\n }\n });\n });\n return Promise.all(promises).then(function(allStats) {\n var results = new Map();\n allStats.forEach(function(stats) {\n stats.forEach(function(stat) {\n results.set(stat.id, stat);\n });\n });\n return results;\n });\n };\n\n // fix low-level stat names and return Map instead of object.\n var ortcObjects = ['RTCRtpSender', 'RTCRtpReceiver', 'RTCIceGatherer',\n 'RTCIceTransport', 'RTCDtlsTransport'];\n ortcObjects.forEach(function(ortcObjectName) {\n var obj = window[ortcObjectName];\n if (obj && obj.prototype && obj.prototype.getStats) {\n var nativeGetstats = obj.prototype.getStats;\n obj.prototype.getStats = function() {\n return nativeGetstats.apply(this)\n .then(function(nativeStats) {\n var mapStats = new Map();\n Object.keys(nativeStats).forEach(function(id) {\n nativeStats[id].type = fixStatsType(nativeStats[id]);\n mapStats.set(id, nativeStats[id]);\n });\n return mapStats;\n });\n };\n }\n });\n\n // legacy callback shims. Should be moved to adapter.js some days.\n var methods = ['createOffer', 'createAnswer'];\n methods.forEach(function(method) {\n var nativeMethod = RTCPeerConnection.prototype[method];\n RTCPeerConnection.prototype[method] = function() {\n var args = arguments;\n if (typeof args[0] === 'function' ||\n typeof args[1] === 'function') { // legacy\n return nativeMethod.apply(this, [arguments[2]])\n .then(function(description) {\n if (typeof args[0] === 'function') {\n args[0].apply(null, [description]);\n }\n }, function(error) {\n if (typeof args[1] === 'function') {\n args[1].apply(null, [error]);\n }\n });\n }\n return nativeMethod.apply(this, arguments);\n };\n });\n\n methods = ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate'];\n methods.forEach(function(method) {\n var nativeMethod = RTCPeerConnection.prototype[method];\n RTCPeerConnection.prototype[method] = function() {\n var args = arguments;\n if (typeof args[1] === 'function' ||\n typeof args[2] === 'function') { // legacy\n return nativeMethod.apply(this, arguments)\n .then(function() {\n if (typeof args[1] === 'function') {\n args[1].apply(null);\n }\n }, function(error) {\n if (typeof args[2] === 'function') {\n args[2].apply(null, [error]);\n }\n });\n }\n return nativeMethod.apply(this, arguments);\n };\n });\n\n // getStats is special. It doesn't have a spec legacy method yet we support\n // getStats(something, cb) without error callbacks.\n ['getStats'].forEach(function(method) {\n var nativeMethod = RTCPeerConnection.prototype[method];\n RTCPeerConnection.prototype[method] = function() {\n var args = arguments;\n if (typeof args[1] === 'function') {\n return nativeMethod.apply(this, arguments)\n .then(function() {\n if (typeof args[1] === 'function') {\n args[1].apply(null);\n }\n });\n }\n return nativeMethod.apply(this, arguments);\n };\n });\n\n return RTCPeerConnection;\n};\n","/*\n * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n /* eslint-env node */\n'use strict';\n\nexport function shimGetUserMedia(window) {\n const navigator = window && window.navigator;\n\n const shimError_ = function(e) {\n return {\n name: {PermissionDeniedError: 'NotAllowedError'}[e.name] || e.name,\n message: e.message,\n constraint: e.constraint,\n toString() {\n return this.name;\n }\n };\n };\n\n // getUserMedia error shim.\n const origGetUserMedia = navigator.mediaDevices.getUserMedia.\n bind(navigator.mediaDevices);\n navigator.mediaDevices.getUserMedia = function(c) {\n return origGetUserMedia(c).catch(e => Promise.reject(shimError_(e)));\n };\n}\n","/*\n * Copyright (c) 2018 The adapter.js project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n /* eslint-env node */\n'use strict';\n\nexport function shimGetDisplayMedia(window) {\n if (!('getDisplayMedia' in window.navigator)) {\n return;\n }\n if (!(window.navigator.mediaDevices)) {\n return;\n }\n if (window.navigator.mediaDevices &&\n 'getDisplayMedia' in window.navigator.mediaDevices) {\n return;\n }\n window.navigator.mediaDevices.getDisplayMedia =\n window.navigator.getDisplayMedia.bind(window.navigator);\n}\n","/*\n * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n/* eslint-env node */\n'use strict';\n\nimport * as utils from '../utils';\nimport {filterIceServers} from './filtericeservers';\nimport shimRTCPeerConnection from 'rtcpeerconnection-shim';\n\nexport {shimGetUserMedia} from './getusermedia';\nexport {shimGetDisplayMedia} from './getdisplaymedia';\n\nexport function shimPeerConnection(window, browserDetails) {\n if (window.RTCIceGatherer) {\n if (!window.RTCIceCandidate) {\n window.RTCIceCandidate = function RTCIceCandidate(args) {\n return args;\n };\n }\n if (!window.RTCSessionDescription) {\n window.RTCSessionDescription = function RTCSessionDescription(args) {\n return args;\n };\n }\n // this adds an additional event listener to MediaStrackTrack that signals\n // when a tracks enabled property was changed. Workaround for a bug in\n // addStream, see below. No longer required in 15025+\n if (browserDetails.version < 15025) {\n const origMSTEnabled = Object.getOwnPropertyDescriptor(\n window.MediaStreamTrack.prototype, 'enabled');\n Object.defineProperty(window.MediaStreamTrack.prototype, 'enabled', {\n set(value) {\n origMSTEnabled.set.call(this, value);\n const ev = new Event('enabled');\n ev.enabled = value;\n this.dispatchEvent(ev);\n }\n });\n }\n }\n\n // ORTC defines the DTMF sender a bit different.\n // https://github.com/w3c/ortc/issues/714\n if (window.RTCRtpSender && !('dtmf' in window.RTCRtpSender.prototype)) {\n Object.defineProperty(window.RTCRtpSender.prototype, 'dtmf', {\n get() {\n if (this._dtmf === undefined) {\n if (this.track.kind === 'audio') {\n this._dtmf = new window.RTCDtmfSender(this);\n } else if (this.track.kind === 'video') {\n this._dtmf = null;\n }\n }\n return this._dtmf;\n }\n });\n }\n // Edge currently only implements the RTCDtmfSender, not the\n // RTCDTMFSender alias. See http://draft.ortc.org/#rtcdtmfsender2*\n if (window.RTCDtmfSender && !window.RTCDTMFSender) {\n window.RTCDTMFSender = window.RTCDtmfSender;\n }\n\n const RTCPeerConnectionShim = shimRTCPeerConnection(window,\n browserDetails.version);\n window.RTCPeerConnection = function RTCPeerConnection(config) {\n if (config && config.iceServers) {\n config.iceServers = filterIceServers(config.iceServers,\n browserDetails.version);\n utils.log('ICE servers after filtering:', config.iceServers);\n }\n return new RTCPeerConnectionShim(config);\n };\n window.RTCPeerConnection.prototype = RTCPeerConnectionShim.prototype;\n}\n\nexport function shimReplaceTrack(window) {\n // ORTC has replaceTrack -- https://github.com/w3c/ortc/issues/614\n if (window.RTCRtpSender &&\n !('replaceTrack' in window.RTCRtpSender.prototype)) {\n window.RTCRtpSender.prototype.replaceTrack =\n window.RTCRtpSender.prototype.setTrack;\n }\n}\n","/*\n * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n/* eslint-env node */\n'use strict';\n\nimport * as utils from '../utils';\n\nexport function shimGetUserMedia(window, browserDetails) {\n const navigator = window && window.navigator;\n const MediaStreamTrack = window && window.MediaStreamTrack;\n\n navigator.getUserMedia = function(constraints, onSuccess, onError) {\n // Replace Firefox 44+'s deprecation warning with unprefixed version.\n utils.deprecated('navigator.getUserMedia',\n 'navigator.mediaDevices.getUserMedia');\n navigator.mediaDevices.getUserMedia(constraints).then(onSuccess, onError);\n };\n\n if (!(browserDetails.version > 55 &&\n 'autoGainControl' in navigator.mediaDevices.getSupportedConstraints())) {\n const remap = function(obj, a, b) {\n if (a in obj && !(b in obj)) {\n obj[b] = obj[a];\n delete obj[a];\n }\n };\n\n const nativeGetUserMedia = navigator.mediaDevices.getUserMedia.\n bind(navigator.mediaDevices);\n navigator.mediaDevices.getUserMedia = function(c) {\n if (typeof c === 'object' && typeof c.audio === 'object') {\n c = JSON.parse(JSON.stringify(c));\n remap(c.audio, 'autoGainControl', 'mozAutoGainControl');\n remap(c.audio, 'noiseSuppression', 'mozNoiseSuppression');\n }\n return nativeGetUserMedia(c);\n };\n\n if (MediaStreamTrack && MediaStreamTrack.prototype.getSettings) {\n const nativeGetSettings = MediaStreamTrack.prototype.getSettings;\n MediaStreamTrack.prototype.getSettings = function() {\n const obj = nativeGetSettings.apply(this, arguments);\n remap(obj, 'mozAutoGainControl', 'autoGainControl');\n remap(obj, 'mozNoiseSuppression', 'noiseSuppression');\n return obj;\n };\n }\n\n if (MediaStreamTrack && MediaStreamTrack.prototype.applyConstraints) {\n const nativeApplyConstraints =\n MediaStreamTrack.prototype.applyConstraints;\n MediaStreamTrack.prototype.applyConstraints = function(c) {\n if (this.kind === 'audio' && typeof c === 'object') {\n c = JSON.parse(JSON.stringify(c));\n remap(c, 'autoGainControl', 'mozAutoGainControl');\n remap(c, 'noiseSuppression', 'mozNoiseSuppression');\n }\n return nativeApplyConstraints.apply(this, [c]);\n };\n }\n }\n}\n","/*\n * Copyright (c) 2018 The adapter.js project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n/* eslint-env node */\n'use strict';\n\nexport function shimGetDisplayMedia(window, preferredMediaSource) {\n if (window.navigator.mediaDevices &&\n 'getDisplayMedia' in window.navigator.mediaDevices) {\n return;\n }\n if (!(window.navigator.mediaDevices)) {\n return;\n }\n window.navigator.mediaDevices.getDisplayMedia =\n function getDisplayMedia(constraints) {\n if (!(constraints && constraints.video)) {\n const err = new DOMException('getDisplayMedia without video ' +\n 'constraints is undefined');\n err.name = 'NotFoundError';\n // from https://heycam.github.io/webidl/#idl-DOMException-error-names\n err.code = 8;\n return Promise.reject(err);\n }\n if (constraints.video === true) {\n constraints.video = {mediaSource: preferredMediaSource};\n } else {\n constraints.video.mediaSource = preferredMediaSource;\n }\n return window.navigator.mediaDevices.getUserMedia(constraints);\n };\n}\n","/*\n * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n/* eslint-env node */\n'use strict';\n\nimport * as utils from '../utils';\nexport {shimGetUserMedia} from './getusermedia';\nexport {shimGetDisplayMedia} from './getdisplaymedia';\n\nexport function shimOnTrack(window) {\n if (typeof window === 'object' && window.RTCTrackEvent &&\n ('receiver' in window.RTCTrackEvent.prototype) &&\n !('transceiver' in window.RTCTrackEvent.prototype)) {\n Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', {\n get() {\n return {receiver: this.receiver};\n }\n });\n }\n}\n\nexport function shimPeerConnection(window, browserDetails) {\n if (typeof window !== 'object' ||\n !(window.RTCPeerConnection || window.mozRTCPeerConnection)) {\n return; // probably media.peerconnection.enabled=false in about:config\n }\n if (!window.RTCPeerConnection && window.mozRTCPeerConnection) {\n // very basic support for old versions.\n window.RTCPeerConnection = window.mozRTCPeerConnection;\n }\n\n if (browserDetails.version < 53) {\n // shim away need for obsolete RTCIceCandidate/RTCSessionDescription.\n ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']\n .forEach(function(method) {\n const nativeMethod = window.RTCPeerConnection.prototype[method];\n const methodObj = {[method]() {\n arguments[0] = new ((method === 'addIceCandidate') ?\n window.RTCIceCandidate :\n window.RTCSessionDescription)(arguments[0]);\n return nativeMethod.apply(this, arguments);\n }};\n window.RTCPeerConnection.prototype[method] = methodObj[method];\n });\n }\n\n const modernStatsTypes = {\n inboundrtp: 'inbound-rtp',\n outboundrtp: 'outbound-rtp',\n candidatepair: 'candidate-pair',\n localcandidate: 'local-candidate',\n remotecandidate: 'remote-candidate'\n };\n\n const nativeGetStats = window.RTCPeerConnection.prototype.getStats;\n window.RTCPeerConnection.prototype.getStats = function getStats() {\n const [selector, onSucc, onErr] = arguments;\n return nativeGetStats.apply(this, [selector || null])\n .then(stats => {\n if (browserDetails.version < 53 && !onSucc) {\n // Shim only promise getStats with spec-hyphens in type names\n // Leave callback version alone; misc old uses of forEach before Map\n try {\n stats.forEach(stat => {\n stat.type = modernStatsTypes[stat.type] || stat.type;\n });\n } catch (e) {\n if (e.name !== 'TypeError') {\n throw e;\n }\n // Avoid TypeError: \"type\" is read-only, in old versions. 34-43ish\n stats.forEach((stat, i) => {\n stats.set(i, Object.assign({}, stat, {\n type: modernStatsTypes[stat.type] || stat.type\n }));\n });\n }\n }\n return stats;\n })\n .then(onSucc, onErr);\n };\n}\n\nexport function shimSenderGetStats(window) {\n if (!(typeof window === 'object' && window.RTCPeerConnection &&\n window.RTCRtpSender)) {\n return;\n }\n if (window.RTCRtpSender && 'getStats' in window.RTCRtpSender.prototype) {\n return;\n }\n const origGetSenders = window.RTCPeerConnection.prototype.getSenders;\n if (origGetSenders) {\n window.RTCPeerConnection.prototype.getSenders = function getSenders() {\n const senders = origGetSenders.apply(this, []);\n senders.forEach(sender => sender._pc = this);\n return senders;\n };\n }\n\n const origAddTrack = window.RTCPeerConnection.prototype.addTrack;\n if (origAddTrack) {\n window.RTCPeerConnection.prototype.addTrack = function addTrack() {\n const sender = origAddTrack.apply(this, arguments);\n sender._pc = this;\n return sender;\n };\n }\n window.RTCRtpSender.prototype.getStats = function getStats() {\n return this.track ? this._pc.getStats(this.track) :\n Promise.resolve(new Map());\n };\n}\n\nexport function shimReceiverGetStats(window) {\n if (!(typeof window === 'object' && window.RTCPeerConnection &&\n window.RTCRtpSender)) {\n return;\n }\n if (window.RTCRtpSender && 'getStats' in window.RTCRtpReceiver.prototype) {\n return;\n }\n const origGetReceivers = window.RTCPeerConnection.prototype.getReceivers;\n if (origGetReceivers) {\n window.RTCPeerConnection.prototype.getReceivers = function getReceivers() {\n const receivers = origGetReceivers.apply(this, []);\n receivers.forEach(receiver => receiver._pc = this);\n return receivers;\n };\n }\n utils.wrapPeerConnectionEvent(window, 'track', e => {\n e.receiver._pc = e.srcElement;\n return e;\n });\n window.RTCRtpReceiver.prototype.getStats = function getStats() {\n return this._pc.getStats(this.track);\n };\n}\n\nexport function shimRemoveStream(window) {\n if (!window.RTCPeerConnection ||\n 'removeStream' in window.RTCPeerConnection.prototype) {\n return;\n }\n window.RTCPeerConnection.prototype.removeStream =\n function removeStream(stream) {\n utils.deprecated('removeStream', 'removeTrack');\n this.getSenders().forEach(sender => {\n if (sender.track && stream.getTracks().includes(sender.track)) {\n this.removeTrack(sender);\n }\n });\n };\n}\n\nexport function shimRTCDataChannel(window) {\n // rename DataChannel to RTCDataChannel (native fix in FF60):\n // https://bugzilla.mozilla.org/show_bug.cgi?id=1173851\n if (window.DataChannel && !window.RTCDataChannel) {\n window.RTCDataChannel = window.DataChannel;\n }\n}\n\nexport function shimAddTransceiver(window) {\n // https://github.com/webrtcHacks/adapter/issues/998#issuecomment-516921647\n // Firefox ignores the init sendEncodings options passed to addTransceiver\n // https://bugzilla.mozilla.org/show_bug.cgi?id=1396918\n if (!(typeof window === 'object' && window.RTCPeerConnection)) {\n return;\n }\n const origAddTransceiver = window.RTCPeerConnection.prototype.addTransceiver;\n if (origAddTransceiver) {\n window.RTCPeerConnection.prototype.addTransceiver =\n function addTransceiver() {\n this.setParametersPromises = [];\n const initParameters = arguments[1];\n const shouldPerformCheck = initParameters &&\n 'sendEncodings' in initParameters;\n if (shouldPerformCheck) {\n // If sendEncodings params are provided, validate grammar\n initParameters.sendEncodings.forEach((encodingParam) => {\n if ('rid' in encodingParam) {\n const ridRegex = /^[a-z0-9]{0,16}$/i;\n if (!ridRegex.test(encodingParam.rid)) {\n throw new TypeError('Invalid RID value provided.');\n }\n }\n if ('scaleResolutionDownBy' in encodingParam) {\n if (!(parseFloat(encodingParam.scaleResolutionDownBy) >= 1.0)) {\n throw new RangeError('scale_resolution_down_by must be >= 1.0');\n }\n }\n if ('maxFramerate' in encodingParam) {\n if (!(parseFloat(encodingParam.maxFramerate) >= 0)) {\n throw new RangeError('max_framerate must be >= 0.0');\n }\n }\n });\n }\n const transceiver = origAddTransceiver.apply(this, arguments);\n if (shouldPerformCheck) {\n // Check if the init options were applied. If not we do this in an\n // asynchronous way and save the promise reference in a global object.\n // This is an ugly hack, but at the same time is way more robust than\n // checking the sender parameters before and after the createOffer\n // Also note that after the createoffer we are not 100% sure that\n // the params were asynchronously applied so we might miss the\n // opportunity to recreate offer.\n const {sender} = transceiver;\n const params = sender.getParameters();\n if (!('encodings' in params) ||\n // Avoid being fooled by patched getParameters() below.\n (params.encodings.length === 1 &&\n Object.keys(params.encodings[0]).length === 0)) {\n params.encodings = initParameters.sendEncodings;\n sender.sendEncodings = initParameters.sendEncodings;\n this.setParametersPromises.push(sender.setParameters(params)\n .then(() => {\n delete sender.sendEncodings;\n }).catch(() => {\n delete sender.sendEncodings;\n })\n );\n }\n }\n return transceiver;\n };\n }\n}\n\nexport function shimGetParameters(window) {\n if (!(typeof window === 'object' && window.RTCRtpSender)) {\n return;\n }\n const origGetParameters = window.RTCRtpSender.prototype.getParameters;\n if (origGetParameters) {\n window.RTCRtpSender.prototype.getParameters =\n function getParameters() {\n const params = origGetParameters.apply(this, arguments);\n if (!('encodings' in params)) {\n params.encodings = [].concat(this.sendEncodings || [{}]);\n }\n return params;\n };\n }\n}\n\nexport function shimCreateOffer(window) {\n // https://github.com/webrtcHacks/adapter/issues/998#issuecomment-516921647\n // Firefox ignores the init sendEncodings options passed to addTransceiver\n // https://bugzilla.mozilla.org/show_bug.cgi?id=1396918\n if (!(typeof window === 'object' && window.RTCPeerConnection)) {\n return;\n }\n const origCreateOffer = window.RTCPeerConnection.prototype.createOffer;\n window.RTCPeerConnection.prototype.createOffer = function createOffer() {\n if (this.setParametersPromises && this.setParametersPromises.length) {\n return Promise.all(this.setParametersPromises)\n .then(() => {\n return origCreateOffer.apply(this, arguments);\n })\n .finally(() => {\n this.setParametersPromises = [];\n });\n }\n return origCreateOffer.apply(this, arguments);\n };\n}\n\nexport function shimCreateAnswer(window) {\n // https://github.com/webrtcHacks/adapter/issues/998#issuecomment-516921647\n // Firefox ignores the init sendEncodings options passed to addTransceiver\n // https://bugzilla.mozilla.org/show_bug.cgi?id=1396918\n if (!(typeof window === 'object' && window.RTCPeerConnection)) {\n return;\n }\n const origCreateAnswer = window.RTCPeerConnection.prototype.createAnswer;\n window.RTCPeerConnection.prototype.createAnswer = function createAnswer() {\n if (this.setParametersPromises && this.setParametersPromises.length) {\n return Promise.all(this.setParametersPromises)\n .then(() => {\n return origCreateAnswer.apply(this, arguments);\n })\n .finally(() => {\n this.setParametersPromises = [];\n });\n }\n return origCreateAnswer.apply(this, arguments);\n };\n}\n","/*\n * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n'use strict';\nimport * as utils from '../utils';\n\nexport function shimLocalStreamsAPI(window) {\n if (typeof window !== 'object' || !window.RTCPeerConnection) {\n return;\n }\n if (!('getLocalStreams' in window.RTCPeerConnection.prototype)) {\n window.RTCPeerConnection.prototype.getLocalStreams =\n function getLocalStreams() {\n if (!this._localStreams) {\n this._localStreams = [];\n }\n return this._localStreams;\n };\n }\n if (!('addStream' in window.RTCPeerConnection.prototype)) {\n const _addTrack = window.RTCPeerConnection.prototype.addTrack;\n window.RTCPeerConnection.prototype.addStream = function addStream(stream) {\n if (!this._localStreams) {\n this._localStreams = [];\n }\n if (!this._localStreams.includes(stream)) {\n this._localStreams.push(stream);\n }\n // Try to emulate Chrome's behaviour of adding in audio-video order.\n // Safari orders by track id.\n stream.getAudioTracks().forEach(track => _addTrack.call(this, track,\n stream));\n stream.getVideoTracks().forEach(track => _addTrack.call(this, track,\n stream));\n };\n\n window.RTCPeerConnection.prototype.addTrack =\n function addTrack(track, ...streams) {\n if (streams) {\n streams.forEach((stream) => {\n if (!this._localStreams) {\n this._localStreams = [stream];\n } else if (!this._localStreams.includes(stream)) {\n this._localStreams.push(stream);\n }\n });\n }\n return _addTrack.apply(this, arguments);\n };\n }\n if (!('removeStream' in window.RTCPeerConnection.prototype)) {\n window.RTCPeerConnection.prototype.removeStream =\n function removeStream(stream) {\n if (!this._localStreams) {\n this._localStreams = [];\n }\n const index = this._localStreams.indexOf(stream);\n if (index === -1) {\n return;\n }\n this._localStreams.splice(index, 1);\n const tracks = stream.getTracks();\n this.getSenders().forEach(sender => {\n if (tracks.includes(sender.track)) {\n this.removeTrack(sender);\n }\n });\n };\n }\n}\n\nexport function shimRemoteStreamsAPI(window) {\n if (typeof window !== 'object' || !window.RTCPeerConnection) {\n return;\n }\n if (!('getRemoteStreams' in window.RTCPeerConnection.prototype)) {\n window.RTCPeerConnection.prototype.getRemoteStreams =\n function getRemoteStreams() {\n return this._remoteStreams ? this._remoteStreams : [];\n };\n }\n if (!('onaddstream' in window.RTCPeerConnection.prototype)) {\n Object.defineProperty(window.RTCPeerConnection.prototype, 'onaddstream', {\n get() {\n return this._onaddstream;\n },\n set(f) {\n if (this._onaddstream) {\n this.removeEventListener('addstream', this._onaddstream);\n this.removeEventListener('track', this._onaddstreampoly);\n }\n this.addEventListener('addstream', this._onaddstream = f);\n this.addEventListener('track', this._onaddstreampoly = (e) => {\n e.streams.forEach(stream => {\n if (!this._remoteStreams) {\n this._remoteStreams = [];\n }\n if (this._remoteStreams.includes(stream)) {\n return;\n }\n this._remoteStreams.push(stream);\n const event = new Event('addstream');\n event.stream = stream;\n this.dispatchEvent(event);\n });\n });\n }\n });\n const origSetRemoteDescription =\n window.RTCPeerConnection.prototype.setRemoteDescription;\n window.RTCPeerConnection.prototype.setRemoteDescription =\n function setRemoteDescription() {\n const pc = this;\n if (!this._onaddstreampoly) {\n this.addEventListener('track', this._onaddstreampoly = function(e) {\n e.streams.forEach(stream => {\n if (!pc._remoteStreams) {\n pc._remoteStreams = [];\n }\n if (pc._remoteStreams.indexOf(stream) >= 0) {\n return;\n }\n pc._remoteStreams.push(stream);\n const event = new Event('addstream');\n event.stream = stream;\n pc.dispatchEvent(event);\n });\n });\n }\n return origSetRemoteDescription.apply(pc, arguments);\n };\n }\n}\n\nexport function shimCallbacksAPI(window) {\n if (typeof window !== 'object' || !window.RTCPeerConnection) {\n return;\n }\n const prototype = window.RTCPeerConnection.prototype;\n const origCreateOffer = prototype.createOffer;\n const origCreateAnswer = prototype.createAnswer;\n const setLocalDescription = prototype.setLocalDescription;\n const setRemoteDescription = prototype.setRemoteDescription;\n const addIceCandidate = prototype.addIceCandidate;\n\n prototype.createOffer =\n function createOffer(successCallback, failureCallback) {\n const options = (arguments.length >= 2) ? arguments[2] : arguments[0];\n const promise = origCreateOffer.apply(this, [options]);\n if (!failureCallback) {\n return promise;\n }\n promise.then(successCallback, failureCallback);\n return Promise.resolve();\n };\n\n prototype.createAnswer =\n function createAnswer(successCallback, failureCallback) {\n const options = (arguments.length >= 2) ? arguments[2] : arguments[0];\n const promise = origCreateAnswer.apply(this, [options]);\n if (!failureCallback) {\n return promise;\n }\n promise.then(successCallback, failureCallback);\n return Promise.resolve();\n };\n\n let withCallback = function(description, successCallback, failureCallback) {\n const promise = setLocalDescription.apply(this, [description]);\n if (!failureCallback) {\n return promise;\n }\n promise.then(successCallback, failureCallback);\n return Promise.resolve();\n };\n prototype.setLocalDescription = withCallback;\n\n withCallback = function(description, successCallback, failureCallback) {\n const promise = setRemoteDescription.apply(this, [description]);\n if (!failureCallback) {\n return promise;\n }\n promise.then(successCallback, failureCallback);\n return Promise.resolve();\n };\n prototype.setRemoteDescription = withCallback;\n\n withCallback = function(candidate, successCallback, failureCallback) {\n const promise = addIceCandidate.apply(this, [candidate]);\n if (!failureCallback) {\n return promise;\n }\n promise.then(successCallback, failureCallback);\n return Promise.resolve();\n };\n prototype.addIceCandidate = withCallback;\n}\n\nexport function shimGetUserMedia(window) {\n const navigator = window && window.navigator;\n\n if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {\n // shim not needed in Safari 12.1\n const mediaDevices = navigator.mediaDevices;\n const _getUserMedia = mediaDevices.getUserMedia.bind(mediaDevices);\n navigator.mediaDevices.getUserMedia = (constraints) => {\n return _getUserMedia(shimConstraints(constraints));\n };\n }\n\n if (!navigator.getUserMedia && navigator.mediaDevices &&\n navigator.mediaDevices.getUserMedia) {\n navigator.getUserMedia = function getUserMedia(constraints, cb, errcb) {\n navigator.mediaDevices.getUserMedia(constraints)\n .then(cb, errcb);\n }.bind(navigator);\n }\n}\n\nexport function shimConstraints(constraints) {\n if (constraints && constraints.video !== undefined) {\n return Object.assign({},\n constraints,\n {video: utils.compactObject(constraints.video)}\n );\n }\n\n return constraints;\n}\n\nexport function shimRTCIceServerUrls(window) {\n if (!window.RTCPeerConnection) {\n return;\n }\n // migrate from non-spec RTCIceServer.url to RTCIceServer.urls\n const OrigPeerConnection = window.RTCPeerConnection;\n window.RTCPeerConnection =\n function RTCPeerConnection(pcConfig, pcConstraints) {\n if (pcConfig && pcConfig.iceServers) {\n const newIceServers = [];\n for (let i = 0; i < pcConfig.iceServers.length; i++) {\n let server = pcConfig.iceServers[i];\n if (!server.hasOwnProperty('urls') &&\n server.hasOwnProperty('url')) {\n utils.deprecated('RTCIceServer.url', 'RTCIceServer.urls');\n server = JSON.parse(JSON.stringify(server));\n server.urls = server.url;\n delete server.url;\n newIceServers.push(server);\n } else {\n newIceServers.push(pcConfig.iceServers[i]);\n }\n }\n pcConfig.iceServers = newIceServers;\n }\n return new OrigPeerConnection(pcConfig, pcConstraints);\n };\n window.RTCPeerConnection.prototype = OrigPeerConnection.prototype;\n // wrap static methods. Currently just generateCertificate.\n if ('generateCertificate' in OrigPeerConnection) {\n Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {\n get() {\n return OrigPeerConnection.generateCertificate;\n }\n });\n }\n}\n\nexport function shimTrackEventTransceiver(window) {\n // Add event.transceiver member over deprecated event.receiver\n if (typeof window === 'object' && window.RTCTrackEvent &&\n 'receiver' in window.RTCTrackEvent.prototype &&\n !('transceiver' in window.RTCTrackEvent.prototype)) {\n Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', {\n get() {\n return {receiver: this.receiver};\n }\n });\n }\n}\n\nexport function shimCreateOfferLegacy(window) {\n const origCreateOffer = window.RTCPeerConnection.prototype.createOffer;\n window.RTCPeerConnection.prototype.createOffer =\n function createOffer(offerOptions) {\n if (offerOptions) {\n if (typeof offerOptions.offerToReceiveAudio !== 'undefined') {\n // support bit values\n offerOptions.offerToReceiveAudio =\n !!offerOptions.offerToReceiveAudio;\n }\n const audioTransceiver = this.getTransceivers().find(transceiver =>\n transceiver.receiver.track.kind === 'audio');\n if (offerOptions.offerToReceiveAudio === false && audioTransceiver) {\n if (audioTransceiver.direction === 'sendrecv') {\n if (audioTransceiver.setDirection) {\n audioTransceiver.setDirection('sendonly');\n } else {\n audioTransceiver.direction = 'sendonly';\n }\n } else if (audioTransceiver.direction === 'recvonly') {\n if (audioTransceiver.setDirection) {\n audioTransceiver.setDirection('inactive');\n } else {\n audioTransceiver.direction = 'inactive';\n }\n }\n } else if (offerOptions.offerToReceiveAudio === true &&\n !audioTransceiver) {\n this.addTransceiver('audio');\n }\n\n if (typeof offerOptions.offerToReceiveVideo !== 'undefined') {\n // support bit values\n offerOptions.offerToReceiveVideo =\n !!offerOptions.offerToReceiveVideo;\n }\n const videoTransceiver = this.getTransceivers().find(transceiver =>\n transceiver.receiver.track.kind === 'video');\n if (offerOptions.offerToReceiveVideo === false && videoTransceiver) {\n if (videoTransceiver.direction === 'sendrecv') {\n if (videoTransceiver.setDirection) {\n videoTransceiver.setDirection('sendonly');\n } else {\n videoTransceiver.direction = 'sendonly';\n }\n } else if (videoTransceiver.direction === 'recvonly') {\n if (videoTransceiver.setDirection) {\n videoTransceiver.setDirection('inactive');\n } else {\n videoTransceiver.direction = 'inactive';\n }\n }\n } else if (offerOptions.offerToReceiveVideo === true &&\n !videoTransceiver) {\n this.addTransceiver('video');\n }\n }\n return origCreateOffer.apply(this, arguments);\n };\n}\n\nexport function shimAudioContext(window) {\n if (typeof window !== 'object' || window.AudioContext) {\n return;\n }\n window.AudioContext = window.webkitAudioContext;\n}\n","/*\n * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n/* eslint-env node */\n'use strict';\n\nimport SDPUtils from 'sdp';\nimport * as utils from './utils';\n\nexport function shimRTCIceCandidate(window) {\n // foundation is arbitrarily chosen as an indicator for full support for\n // https://w3c.github.io/webrtc-pc/#rtcicecandidate-interface\n if (!window.RTCIceCandidate || (window.RTCIceCandidate && 'foundation' in\n window.RTCIceCandidate.prototype)) {\n return;\n }\n\n const NativeRTCIceCandidate = window.RTCIceCandidate;\n window.RTCIceCandidate = function RTCIceCandidate(args) {\n // Remove the a= which shouldn't be part of the candidate string.\n if (typeof args === 'object' && args.candidate &&\n args.candidate.indexOf('a=') === 0) {\n args = JSON.parse(JSON.stringify(args));\n args.candidate = args.candidate.substr(2);\n }\n\n if (args.candidate && args.candidate.length) {\n // Augment the native candidate with the parsed fields.\n const nativeCandidate = new NativeRTCIceCandidate(args);\n const parsedCandidate = SDPUtils.parseCandidate(args.candidate);\n const augmentedCandidate = Object.assign(nativeCandidate,\n parsedCandidate);\n\n // Add a serializer that does not serialize the extra attributes.\n augmentedCandidate.toJSON = function toJSON() {\n return {\n candidate: augmentedCandidate.candidate,\n sdpMid: augmentedCandidate.sdpMid,\n sdpMLineIndex: augmentedCandidate.sdpMLineIndex,\n usernameFragment: augmentedCandidate.usernameFragment,\n };\n };\n return augmentedCandidate;\n }\n return new NativeRTCIceCandidate(args);\n };\n window.RTCIceCandidate.prototype = NativeRTCIceCandidate.prototype;\n\n // Hook up the augmented candidate in onicecandidate and\n // addEventListener('icecandidate', ...)\n utils.wrapPeerConnectionEvent(window, 'icecandidate', e => {\n if (e.candidate) {\n Object.defineProperty(e, 'candidate', {\n value: new window.RTCIceCandidate(e.candidate),\n writable: 'false'\n });\n }\n return e;\n });\n}\n\nexport function shimMaxMessageSize(window, browserDetails) {\n if (!window.RTCPeerConnection) {\n return;\n }\n\n if (!('sctp' in window.RTCPeerConnection.prototype)) {\n Object.defineProperty(window.RTCPeerConnection.prototype, 'sctp', {\n get() {\n return typeof this._sctp === 'undefined' ? null : this._sctp;\n }\n });\n }\n\n const sctpInDescription = function(description) {\n if (!description || !description.sdp) {\n return false;\n }\n const sections = SDPUtils.splitSections(description.sdp);\n sections.shift();\n return sections.some(mediaSection => {\n const mLine = SDPUtils.parseMLine(mediaSection);\n return mLine && mLine.kind === 'application'\n && mLine.protocol.indexOf('SCTP') !== -1;\n });\n };\n\n const getRemoteFirefoxVersion = function(description) {\n // TODO: Is there a better solution for detecting Firefox?\n const match = description.sdp.match(/mozilla...THIS_IS_SDPARTA-(\\d+)/);\n if (match === null || match.length < 2) {\n return -1;\n }\n const version = parseInt(match[1], 10);\n // Test for NaN (yes, this is ugly)\n return version !== version ? -1 : version;\n };\n\n const getCanSendMaxMessageSize = function(remoteIsFirefox) {\n // Every implementation we know can send at least 64 KiB.\n // Note: Although Chrome is technically able to send up to 256 KiB, the\n // data does not reach the other peer reliably.\n // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=8419\n let canSendMaxMessageSize = 65536;\n if (browserDetails.browser === 'firefox') {\n if (browserDetails.version < 57) {\n if (remoteIsFirefox === -1) {\n // FF < 57 will send in 16 KiB chunks using the deprecated PPID\n // fragmentation.\n canSendMaxMessageSize = 16384;\n } else {\n // However, other FF (and RAWRTC) can reassemble PPID-fragmented\n // messages. Thus, supporting ~2 GiB when sending.\n canSendMaxMessageSize = 2147483637;\n }\n } else if (browserDetails.version < 60) {\n // Currently, all FF >= 57 will reset the remote maximum message size\n // to the default value when a data channel is created at a later\n // stage. :(\n // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831\n canSendMaxMessageSize =\n browserDetails.version === 57 ? 65535 : 65536;\n } else {\n // FF >= 60 supports sending ~2 GiB\n canSendMaxMessageSize = 2147483637;\n }\n }\n return canSendMaxMessageSize;\n };\n\n const getMaxMessageSize = function(description, remoteIsFirefox) {\n // Note: 65536 bytes is the default value from the SDP spec. Also,\n // every implementation we know supports receiving 65536 bytes.\n let maxMessageSize = 65536;\n\n // FF 57 has a slightly incorrect default remote max message size, so\n // we need to adjust it here to avoid a failure when sending.\n // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1425697\n if (browserDetails.browser === 'firefox'\n && browserDetails.version === 57) {\n maxMessageSize = 65535;\n }\n\n const match = SDPUtils.matchPrefix(description.sdp,\n 'a=max-message-size:');\n if (match.length > 0) {\n maxMessageSize = parseInt(match[0].substr(19), 10);\n } else if (browserDetails.browser === 'firefox' &&\n remoteIsFirefox !== -1) {\n // If the maximum message size is not present in the remote SDP and\n // both local and remote are Firefox, the remote peer can receive\n // ~2 GiB.\n maxMessageSize = 2147483637;\n }\n return maxMessageSize;\n };\n\n const origSetRemoteDescription =\n window.RTCPeerConnection.prototype.setRemoteDescription;\n window.RTCPeerConnection.prototype.setRemoteDescription =\n function setRemoteDescription() {\n this._sctp = null;\n // Chrome decided to not expose .sctp in plan-b mode.\n // As usual, adapter.js has to do an 'ugly worakaround'\n // to cover up the mess.\n if (browserDetails.browser === 'chrome' && browserDetails.version >= 76) {\n const {sdpSemantics} = this.getConfiguration();\n if (sdpSemantics === 'plan-b') {\n Object.defineProperty(this, 'sctp', {\n get() {\n return typeof this._sctp === 'undefined' ? null : this._sctp;\n },\n enumerable: true,\n configurable: true,\n });\n }\n }\n\n if (sctpInDescription(arguments[0])) {\n // Check if the remote is FF.\n const isFirefox = getRemoteFirefoxVersion(arguments[0]);\n\n // Get the maximum message size the local peer is capable of sending\n const canSendMMS = getCanSendMaxMessageSize(isFirefox);\n\n // Get the maximum message size of the remote peer.\n const remoteMMS = getMaxMessageSize(arguments[0], isFirefox);\n\n // Determine final maximum message size\n let maxMessageSize;\n if (canSendMMS === 0 && remoteMMS === 0) {\n maxMessageSize = Number.POSITIVE_INFINITY;\n } else if (canSendMMS === 0 || remoteMMS === 0) {\n maxMessageSize = Math.max(canSendMMS, remoteMMS);\n } else {\n maxMessageSize = Math.min(canSendMMS, remoteMMS);\n }\n\n // Create a dummy RTCSctpTransport object and the 'maxMessageSize'\n // attribute.\n const sctp = {};\n Object.defineProperty(sctp, 'maxMessageSize', {\n get() {\n return maxMessageSize;\n }\n });\n this._sctp = sctp;\n }\n\n return origSetRemoteDescription.apply(this, arguments);\n };\n}\n\nexport function shimSendThrowTypeError(window) {\n if (!(window.RTCPeerConnection &&\n 'createDataChannel' in window.RTCPeerConnection.prototype)) {\n return;\n }\n\n // Note: Although Firefox >= 57 has a native implementation, the maximum\n // message size can be reset for all data channels at a later stage.\n // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831\n\n function wrapDcSend(dc, pc) {\n const origDataChannelSend = dc.send;\n dc.send = function send() {\n const data = arguments[0];\n const length = data.length || data.size || data.byteLength;\n if (dc.readyState === 'open' &&\n pc.sctp && length > pc.sctp.maxMessageSize) {\n throw new TypeError('Message too large (can send a maximum of ' +\n pc.sctp.maxMessageSize + ' bytes)');\n }\n return origDataChannelSend.apply(dc, arguments);\n };\n }\n const origCreateDataChannel =\n window.RTCPeerConnection.prototype.createDataChannel;\n window.RTCPeerConnection.prototype.createDataChannel =\n function createDataChannel() {\n const dataChannel = origCreateDataChannel.apply(this, arguments);\n wrapDcSend(dataChannel, this);\n return dataChannel;\n };\n utils.wrapPeerConnectionEvent(window, 'datachannel', e => {\n wrapDcSend(e.channel, e.target);\n return e;\n });\n}\n\n\n/* shims RTCConnectionState by pretending it is the same as iceConnectionState.\n * See https://bugs.chromium.org/p/webrtc/issues/detail?id=6145#c12\n * for why this is a valid hack in Chrome. In Firefox it is slightly incorrect\n * since DTLS failures would be hidden. See\n * https://bugzilla.mozilla.org/show_bug.cgi?id=1265827\n * for the Firefox tracking bug.\n */\nexport function shimConnectionState(window) {\n if (!window.RTCPeerConnection ||\n 'connectionState' in window.RTCPeerConnection.prototype) {\n return;\n }\n const proto = window.RTCPeerConnection.prototype;\n Object.defineProperty(proto, 'connectionState', {\n get() {\n return {\n completed: 'connected',\n checking: 'connecting'\n }[this.iceConnectionState] || this.iceConnectionState;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(proto, 'onconnectionstatechange', {\n get() {\n return this._onconnectionstatechange || null;\n },\n set(cb) {\n if (this._onconnectionstatechange) {\n this.removeEventListener('connectionstatechange',\n this._onconnectionstatechange);\n delete this._onconnectionstatechange;\n }\n if (cb) {\n this.addEventListener('connectionstatechange',\n this._onconnectionstatechange = cb);\n }\n },\n enumerable: true,\n configurable: true\n });\n\n ['setLocalDescription', 'setRemoteDescription'].forEach((method) => {\n const origMethod = proto[method];\n proto[method] = function() {\n if (!this._connectionstatechangepoly) {\n this._connectionstatechangepoly = e => {\n const pc = e.target;\n if (pc._lastConnectionState !== pc.connectionState) {\n pc._lastConnectionState = pc.connectionState;\n const newEvent = new Event('connectionstatechange', e);\n pc.dispatchEvent(newEvent);\n }\n return e;\n };\n this.addEventListener('iceconnectionstatechange',\n this._connectionstatechangepoly);\n }\n return origMethod.apply(this, arguments);\n };\n });\n}\n\nexport function removeExtmapAllowMixed(window, browserDetails) {\n /* remove a=extmap-allow-mixed for webrtc.org < M71 */\n if (!window.RTCPeerConnection) {\n return;\n }\n if (browserDetails.browser === 'chrome' && browserDetails.version >= 71) {\n return;\n }\n if (browserDetails.browser === 'safari' && browserDetails.version >= 605) {\n return;\n }\n const nativeSRD = window.RTCPeerConnection.prototype.setRemoteDescription;\n window.RTCPeerConnection.prototype.setRemoteDescription =\n function setRemoteDescription(desc) {\n if (desc && desc.sdp && desc.sdp.indexOf('\\na=extmap-allow-mixed') !== -1) {\n const sdp = desc.sdp.split('\\n').filter((line) => {\n return line.trim() !== 'a=extmap-allow-mixed';\n }).join('\\n');\n // Safari enforces read-only-ness of RTCSessionDescription fields.\n if (window.RTCSessionDescription &&\n desc instanceof window.RTCSessionDescription) {\n arguments[0] = new window.RTCSessionDescription({\n type: desc.type,\n sdp,\n });\n } else {\n desc.sdp = sdp;\n }\n }\n return nativeSRD.apply(this, arguments);\n };\n}\n\nexport function shimAddIceCandidateNullOrEmpty(window, browserDetails) {\n // Support for addIceCandidate(null or undefined)\n // as well as addIceCandidate({candidate: \"\", ...})\n // https://bugs.chromium.org/p/chromium/issues/detail?id=978582\n // Note: must be called before other polyfills which change the signature.\n if (!(window.RTCPeerConnection && window.RTCPeerConnection.prototype)) {\n return;\n }\n const nativeAddIceCandidate =\n window.RTCPeerConnection.prototype.addIceCandidate;\n if (!nativeAddIceCandidate || nativeAddIceCandidate.length === 0) {\n return;\n }\n window.RTCPeerConnection.prototype.addIceCandidate =\n function addIceCandidate() {\n if (!arguments[0]) {\n if (arguments[1]) {\n arguments[1].apply(null);\n }\n return Promise.resolve();\n }\n // Firefox 68+ emits and processes {candidate: \"\", ...}, ignore\n // in older versions.\n // Native support for ignoring exists for Chrome M77+.\n // Safari ignores as well, exact version unknown but works in the same\n // version that also ignores addIceCandidate(null).\n if (((browserDetails.browser === 'chrome' && browserDetails.version < 78)\n || (browserDetails.browser === 'firefox'\n && browserDetails.version < 68)\n || (browserDetails.browser === 'safari'))\n && arguments[0] && arguments[0].candidate === '') {\n return Promise.resolve();\n }\n return nativeAddIceCandidate.apply(this, arguments);\n };\n}\n","/*\n * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\nimport * as utils from './utils';\n\n // Browser shims.\nimport * as chromeShim from './chrome/chrome_shim';\nimport * as edgeShim from './edge/edge_shim';\nimport * as firefoxShim from './firefox/firefox_shim';\nimport * as safariShim from './safari/safari_shim';\nimport * as commonShim from './common_shim';\n\n// Shimming starts here.\nexport function adapterFactory({window} = {}, options = {\n shimChrome: true,\n shimFirefox: true,\n shimEdge: true,\n shimSafari: true,\n}) {\n // Utils.\n const logging = utils.log;\n const browserDetails = utils.detectBrowser(window);\n\n const adapter = {\n browserDetails,\n commonShim,\n extractVersion: utils.extractVersion,\n disableLog: utils.disableLog,\n disableWarnings: utils.disableWarnings\n };\n\n // Shim browser if found.\n switch (browserDetails.browser) {\n case 'chrome':\n if (!chromeShim || !chromeShim.shimPeerConnection ||\n !options.shimChrome) {\n logging('Chrome shim is not included in this adapter release.');\n return adapter;\n }\n if (browserDetails.version === null) {\n logging('Chrome shim can not determine version, not shimming.');\n return adapter;\n }\n logging('adapter.js shimming chrome.');\n // Export to the adapter global object visible in the browser.\n adapter.browserShim = chromeShim;\n\n // Must be called before shimPeerConnection.\n commonShim.shimAddIceCandidateNullOrEmpty(window, browserDetails);\n\n chromeShim.shimGetUserMedia(window, browserDetails);\n chromeShim.shimMediaStream(window, browserDetails);\n chromeShim.shimPeerConnection(window, browserDetails);\n chromeShim.shimOnTrack(window, browserDetails);\n chromeShim.shimAddTrackRemoveTrack(window, browserDetails);\n chromeShim.shimGetSendersWithDtmf(window, browserDetails);\n chromeShim.shimGetStats(window, browserDetails);\n chromeShim.shimSenderReceiverGetStats(window, browserDetails);\n chromeShim.fixNegotiationNeeded(window, browserDetails);\n\n commonShim.shimRTCIceCandidate(window, browserDetails);\n commonShim.shimConnectionState(window, browserDetails);\n commonShim.shimMaxMessageSize(window, browserDetails);\n commonShim.shimSendThrowTypeError(window, browserDetails);\n commonShim.removeExtmapAllowMixed(window, browserDetails);\n break;\n case 'firefox':\n if (!firefoxShim || !firefoxShim.shimPeerConnection ||\n !options.shimFirefox) {\n logging('Firefox shim is not included in this adapter release.');\n return adapter;\n }\n logging('adapter.js shimming firefox.');\n // Export to the adapter global object visible in the browser.\n adapter.browserShim = firefoxShim;\n\n // Must be called before shimPeerConnection.\n commonShim.shimAddIceCandidateNullOrEmpty(window, browserDetails);\n\n firefoxShim.shimGetUserMedia(window, browserDetails);\n firefoxShim.shimPeerConnection(window, browserDetails);\n firefoxShim.shimOnTrack(window, browserDetails);\n firefoxShim.shimRemoveStream(window, browserDetails);\n firefoxShim.shimSenderGetStats(window, browserDetails);\n firefoxShim.shimReceiverGetStats(window, browserDetails);\n firefoxShim.shimRTCDataChannel(window, browserDetails);\n firefoxShim.shimAddTransceiver(window, browserDetails);\n firefoxShim.shimGetParameters(window, browserDetails);\n firefoxShim.shimCreateOffer(window, browserDetails);\n firefoxShim.shimCreateAnswer(window, browserDetails);\n\n commonShim.shimRTCIceCandidate(window, browserDetails);\n commonShim.shimConnectionState(window, browserDetails);\n commonShim.shimMaxMessageSize(window, browserDetails);\n commonShim.shimSendThrowTypeError(window, browserDetails);\n break;\n case 'edge':\n if (!edgeShim || !edgeShim.shimPeerConnection || !options.shimEdge) {\n logging('MS edge shim is not included in this adapter release.');\n return adapter;\n }\n logging('adapter.js shimming edge.');\n // Export to the adapter global object visible in the browser.\n adapter.browserShim = edgeShim;\n\n edgeShim.shimGetUserMedia(window, browserDetails);\n edgeShim.shimGetDisplayMedia(window, browserDetails);\n edgeShim.shimPeerConnection(window, browserDetails);\n edgeShim.shimReplaceTrack(window, browserDetails);\n\n // the edge shim implements the full RTCIceCandidate object.\n\n commonShim.shimMaxMessageSize(window, browserDetails);\n commonShim.shimSendThrowTypeError(window, browserDetails);\n break;\n case 'safari':\n if (!safariShim || !options.shimSafari) {\n logging('Safari shim is not included in this adapter release.');\n return adapter;\n }\n logging('adapter.js shimming safari.');\n // Export to the adapter global object visible in the browser.\n adapter.browserShim = safariShim;\n\n // Must be called before shimCallbackAPI.\n commonShim.shimAddIceCandidateNullOrEmpty(window, browserDetails);\n\n safariShim.shimRTCIceServerUrls(window, browserDetails);\n safariShim.shimCreateOfferLegacy(window, browserDetails);\n safariShim.shimCallbacksAPI(window, browserDetails);\n safariShim.shimLocalStreamsAPI(window, browserDetails);\n safariShim.shimRemoteStreamsAPI(window, browserDetails);\n safariShim.shimTrackEventTransceiver(window, browserDetails);\n safariShim.shimGetUserMedia(window, browserDetails);\n safariShim.shimAudioContext(window, browserDetails);\n\n commonShim.shimRTCIceCandidate(window, browserDetails);\n commonShim.shimMaxMessageSize(window, browserDetails);\n commonShim.shimSendThrowTypeError(window, browserDetails);\n commonShim.removeExtmapAllowMixed(window, browserDetails);\n break;\n default:\n logging('Unsupported browser!');\n break;\n }\n\n return adapter;\n}\n","/*\n * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n/* eslint-env node */\n\n'use strict';\n\nimport {adapterFactory} from './adapter_factory.js';\n\nconst adapter =\n adapterFactory({window: typeof window === 'undefined' ? undefined : window});\nexport default adapter;\n","\n'use strict';\nimport * as utils from './utils.js';\nimport * as MediaFormatModule from './mediaformat.js';\nimport adapter from 'webrtc-adapter';\n\n/**\n * @class AudioTrackConstraints\n * @classDesc Constraints for creating an audio MediaStreamTrack.\n * @memberof Owt.Base\n * @constructor\n * @param {Owt.Base.AudioSourceInfo} source Source info of this audio track.\n */\nexport class AudioTrackConstraints {\n // eslint-disable-next-line require-jsdoc\n constructor(source) {\n if (!Object.values(MediaFormatModule.AudioSourceInfo)\n .some((v) => v === source)) {\n throw new TypeError('Invalid source.');\n }\n /**\n * @member {string} source\n * @memberof Owt.Base.AudioTrackConstraints\n * @desc Values could be \"mic\", \"screen-cast\", \"file\" or \"mixed\".\n * @instance\n */\n this.source = source;\n /**\n * @member {string} deviceId\n * @memberof Owt.Base.AudioTrackConstraints\n * @desc Do not provide deviceId if source is not \"mic\".\n * @instance\n * @see https://w3c.github.io/mediacapture-main/#def-constraint-deviceId\n */\n this.deviceId = undefined;\n }\n}\n\n/**\n * @class VideoTrackConstraints\n * @classDesc Constraints for creating a video MediaStreamTrack.\n * @memberof Owt.Base\n * @constructor\n * @param {Owt.Base.VideoSourceInfo} source Source info of this video track.\n */\nexport class VideoTrackConstraints {\n // eslint-disable-next-line require-jsdoc\n constructor(source) {\n if (!Object.values(MediaFormatModule.VideoSourceInfo)\n .some((v) => v === source)) {\n throw new TypeError('Invalid source.');\n }\n /**\n * @member {string} source\n * @memberof Owt.Base.VideoTrackConstraints\n * @desc Values could be \"camera\", \"screen-cast\", \"file\" or \"mixed\".\n * @instance\n */\n this.source = source;\n /**\n * @member {string} deviceId\n * @memberof Owt.Base.VideoTrackConstraints\n * @desc Do not provide deviceId if source is not \"camera\".\n * @instance\n * @see https://w3c.github.io/mediacapture-main/#def-constraint-deviceId\n */\n\n this.deviceId = undefined;\n\n /**\n * @member {Owt.Base.Resolution} resolution\n * @memberof Owt.Base.VideoTrackConstraints\n * @instance\n */\n this.resolution = undefined;\n\n /**\n * @member {number} frameRate\n * @memberof Owt.Base.VideoTrackConstraints\n * @instance\n */\n this.frameRate = undefined;\n }\n}\n/**\n * @class StreamConstraints\n * @classDesc Constraints for creating a MediaStream from screen mic and camera.\n * @memberof Owt.Base\n * @constructor\n * @param {?Owt.Base.AudioTrackConstraints} audioConstraints\n * @param {?Owt.Base.VideoTrackConstraints} videoConstraints\n */\nexport class StreamConstraints {\n // eslint-disable-next-line require-jsdoc\n constructor(audioConstraints = false, videoConstraints = false) {\n /**\n * @member {Owt.Base.MediaStreamTrackDeviceConstraintsForAudio} audio\n * @memberof Owt.Base.MediaStreamDeviceConstraints\n * @instance\n */\n this.audio = audioConstraints;\n /**\n * @member {Owt.Base.MediaStreamTrackDeviceConstraintsForVideo} Video\n * @memberof Owt.Base.MediaStreamDeviceConstraints\n * @instance\n */\n this.video = videoConstraints;\n }\n}\n\n// eslint-disable-next-line require-jsdoc\nfunction isVideoConstrainsForScreenCast(constraints) {\n return (typeof constraints.video === 'object' && constraints.video.source ===\n MediaFormatModule.VideoSourceInfo.SCREENCAST);\n}\n\n/**\n * @class MediaStreamFactory\n * @classDesc A factory to create MediaStream. You can also create MediaStream by yourself.\n * @memberof Owt.Base\n */\nexport class MediaStreamFactory {\n /**\n * @function createMediaStream\n * @static\n * @desc Create a MediaStream with given constraints. If you want to create a MediaStream for screen cast, please make sure both audio and video's source are \"screen-cast\".\n * @memberof Owt.Base.MediaStreamFactory\n * @return {Promise<MediaStream, Error>} Return a promise that is resolved when stream is successfully created, or rejected if one of the following error happened:\n * - One or more parameters cannot be satisfied.\n * - Specified device is busy.\n * - Cannot obtain necessary permission or operation is canceled by user.\n * - Video source is screen cast, while audio source is not.\n * - Audio source is screen cast, while video source is disabled.\n * @param {Owt.Base.StreamConstraints} constraints\n */\n static createMediaStream(constraints) {\n if (typeof constraints !== 'object' ||\n (!constraints.audio && !constraints.video)) {\n return Promise.reject(new TypeError('Invalid constrains'));\n }\n if (!isVideoConstrainsForScreenCast(constraints) &&\n (typeof constraints.audio === 'object') &&\n constraints.audio.source ===\n MediaFormatModule.AudioSourceInfo.SCREENCAST) {\n return Promise.reject(\n new TypeError('Cannot share screen without video.'));\n }\n if (isVideoConstrainsForScreenCast(constraints) && !utils.isChrome() &&\n !utils.isFirefox()) {\n return Promise.reject(\n new TypeError('Screen sharing only supports Chrome and Firefox.'));\n }\n if (isVideoConstrainsForScreenCast(constraints) &&\n typeof constraints.audio === 'object' &&\n constraints.audio.source !==\n MediaFormatModule.AudioSourceInfo.SCREENCAST) {\n return Promise.reject(new TypeError(\n 'Cannot capture video from screen cast while capture audio from'\n + ' other source.'));\n }\n\n // Check and convert constraints.\n if (!constraints.audio && !constraints.video) {\n return Promise.reject(new TypeError(\n 'At least one of audio and video must be requested.'));\n }\n const mediaConstraints = Object.create({});\n if (typeof constraints.audio === 'object' &&\n constraints.audio.source === MediaFormatModule.AudioSourceInfo.MIC) {\n mediaConstraints.audio = Object.create({});\n if (utils.isEdge()) {\n mediaConstraints.audio.deviceId = constraints.audio.deviceId;\n } else {\n mediaConstraints.audio.deviceId = {\n exact: constraints.audio.deviceId,\n };\n }\n } else {\n if (constraints.audio.source ===\n MediaFormatModule.AudioSourceInfo.SCREENCAST) {\n mediaConstraints.audio = true;\n } else {\n mediaConstraints.audio = constraints.audio;\n }\n }\n if (typeof constraints.video === 'object') {\n mediaConstraints.video = Object.create({});\n if (typeof constraints.video.frameRate === 'number') {\n mediaConstraints.video.frameRate = constraints.video.frameRate;\n }\n if (constraints.video.resolution &&\n constraints.video.resolution.width &&\n constraints.video.resolution.height) {\n if (constraints.video.source ===\n MediaFormatModule.VideoSourceInfo.SCREENCAST) {\n mediaConstraints.video.width = constraints.video.resolution.width;\n mediaConstraints.video.height = constraints.video.resolution.height;\n } else {\n mediaConstraints.video.width = Object.create({});\n mediaConstraints.video.width.exact =\n constraints.video.resolution.width;\n mediaConstraints.video.height = Object.create({});\n mediaConstraints.video.height.exact =\n constraints.video.resolution.height;\n }\n }\n if (typeof constraints.video.deviceId === 'string') {\n mediaConstraints.video.deviceId = {exact: constraints.video.deviceId};\n }\n if (utils.isFirefox() &&\n constraints.video.source ===\n MediaFormatModule.VideoSourceInfo.SCREENCAST) {\n mediaConstraints.video.mediaSource = 'screen';\n }\n } else {\n mediaConstraints.video = constraints.video;\n }\n\n if (isVideoConstrainsForScreenCast(constraints)) {\n return navigator.mediaDevices.getDisplayMedia(mediaConstraints);\n } else {\n return navigator.mediaDevices.getUserMedia(mediaConstraints);\n }\n }\n}\n","// Copyright (C) <2018> Intel Corporation\n//\n// SPDX-License-Identifier: Apache-2.0\n\n'use strict';\n\nexport * from './mediastream-factory.js';\nexport * from './mediaformat.js';","let logger;\nlet errorLogger;\n\nexport function setLogger() {\n /*eslint-disable */\n logger = console.log;\n errorLogger = console.error;\n /*eslint-enable */\n}\n\nexport function isEnable() {\n return logger != null;\n}\n\nexport function log(message, ...optionalParams) {\n if (logger) {\n logger(message, ...optionalParams);\n }\n}\nexport function error(message, ...optionalParams) {\n if (errorLogger) {\n errorLogger(message, ...optionalParams);\n }\n}\n","export default class Event {\n constructor(type) {\n this.listener = {};\n this.type = type | '';\n }\n\n on(event, fn) {\n if (!this.listener[event]) {\n this.listener[event] = [];\n }\n this.listener[event].push(fn);\n return true;\n }\n\n off(event, fn) {\n if (this.listener[event]) {\n var index = this.listener[event].indexOf(fn);\n if (index > -1) {\n this.listener[event].splice(index, 1);\n }\n return true;\n }\n return false;\n }\n\n offAll() {\n this.listener = {};\n }\n\n dispatch(event, data) {\n if (this.listener[event]) {\n this.listener[event].map((each) => {\n each.apply(null, [data]);\n });\n return true;\n }\n return false;\n }\n}\n","'use strict';\n\nmodule.exports = function bind(fn, thisArg) {\n return function wrap() {\n var args = new Array(arguments.length);\n for (var i = 0; i < args.length; i++) {\n args[i] = arguments[i];\n }\n return fn.apply(thisArg, args);\n };\n};\n","'use strict';\n\nvar bind = require('./helpers/bind');\n\n// utils is a library of generic helper functions non-specific to axios\n\nvar toString = Object.prototype.toString;\n\n// eslint-disable-next-line func-names\nvar kindOf = (function(cache) {\n // eslint-disable-next-line func-names\n return function(thing) {\n var str = toString.call(thing);\n return cache[str] || (cache[str] = str.slice(8, -1).toLowerCase());\n };\n})(Object.create(null));\n\nfunction kindOfTest(type) {\n type = type.toLowerCase();\n return function isKindOf(thing) {\n return kindOf(thing) === type;\n };\n}\n\n/**\n * Determine if a value is an Array\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is an Array, otherwise false\n */\nfunction isArray(val) {\n return Array.isArray(val);\n}\n\n/**\n * Determine if a value is undefined\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if the value is undefined, otherwise false\n */\nfunction isUndefined(val) {\n return typeof val === 'undefined';\n}\n\n/**\n * Determine if a value is a Buffer\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Buffer, otherwise false\n */\nfunction isBuffer(val) {\n return val !== null && !isUndefined(val) && val.constructor !== null && !isUndefined(val.constructor)\n && typeof val.constructor.isBuffer === 'function' && val.constructor.isBuffer(val);\n}\n\n/**\n * Determine if a value is an ArrayBuffer\n *\n * @function\n * @param {Object} val The value to test\n * @returns {boolean} True if value is an ArrayBuffer, otherwise false\n */\nvar isArrayBuffer = kindOfTest('ArrayBuffer');\n\n\n/**\n * Determine if a value is a view on an ArrayBuffer\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false\n */\nfunction isArrayBufferView(val) {\n var result;\n if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) {\n result = ArrayBuffer.isView(val);\n } else {\n result = (val) && (val.buffer) && (isArrayBuffer(val.buffer));\n }\n return result;\n}\n\n/**\n * Determine if a value is a String\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a String, otherwise false\n */\nfunction isString(val) {\n return typeof val === 'string';\n}\n\n/**\n * Determine if a value is a Number\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Number, otherwise false\n */\nfunction isNumber(val) {\n return typeof val === 'number';\n}\n\n/**\n * Determine if a value is an Object\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is an Object, otherwise false\n */\nfunction isObject(val) {\n return val !== null && typeof val === 'object';\n}\n\n/**\n * Determine if a value is a plain Object\n *\n * @param {Object} val The value to test\n * @return {boolean} True if value is a plain Object, otherwise false\n */\nfunction isPlainObject(val) {\n if (kindOf(val) !== 'object') {\n return false;\n }\n\n var prototype = Object.getPrototypeOf(val);\n return prototype === null || prototype === Object.prototype;\n}\n\n/**\n * Determine if a value is a Date\n *\n * @function\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Date, otherwise false\n */\nvar isDate = kindOfTest('Date');\n\n/**\n * Determine if a value is a File\n *\n * @function\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a File, otherwise false\n */\nvar isFile = kindOfTest('File');\n\n/**\n * Determine if a value is a Blob\n *\n * @function\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Blob, otherwise false\n */\nvar isBlob = kindOfTest('Blob');\n\n/**\n * Determine if a value is a FileList\n *\n * @function\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a File, otherwise false\n */\nvar isFileList = kindOfTest('FileList');\n\n/**\n * Determine if a value is a Function\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Function, otherwise false\n */\nfunction isFunction(val) {\n return toString.call(val) === '[object Function]';\n}\n\n/**\n * Determine if a value is a Stream\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Stream, otherwise false\n */\nfunction isStream(val) {\n return isObject(val) && isFunction(val.pipe);\n}\n\n/**\n * Determine if a value is a FormData\n *\n * @param {Object} thing The value to test\n * @returns {boolean} True if value is an FormData, otherwise false\n */\nfunction isFormData(thing) {\n var pattern = '[object FormData]';\n return thing && (\n (typeof FormData === 'function' && thing instanceof FormData) ||\n toString.call(thing) === pattern ||\n (isFunction(thing.toString) && thing.toString() === pattern)\n );\n}\n\n/**\n * Determine if a value is a URLSearchParams object\n * @function\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a URLSearchParams object, otherwise false\n */\nvar isURLSearchParams = kindOfTest('URLSearchParams');\n\n/**\n * Trim excess whitespace off the beginning and end of a string\n *\n * @param {String} str The String to trim\n * @returns {String} The String freed of excess whitespace\n */\nfunction trim(str) {\n return str.trim ? str.trim() : str.replace(/^\\s+|\\s+$/g, '');\n}\n\n/**\n * Determine if we're running in a standard browser environment\n *\n * This allows axios to run in a web worker, and react-native.\n * Both environments support XMLHttpRequest, but not fully standard globals.\n *\n * web workers:\n * typeof window -> undefined\n * typeof document -> undefined\n *\n * react-native:\n * navigator.product -> 'ReactNative'\n * nativescript\n * navigator.product -> 'NativeScript' or 'NS'\n */\nfunction isStandardBrowserEnv() {\n if (typeof navigator !== 'undefined' && (navigator.product === 'ReactNative' ||\n navigator.product === 'NativeScript' ||\n navigator.product === 'NS')) {\n return false;\n }\n return (\n typeof window !== 'undefined' &&\n typeof document !== 'undefined'\n );\n}\n\n/**\n * Iterate over an Array or an Object invoking a function for each item.\n *\n * If `obj` is an Array callback will be called passing\n * the value, index, and complete array for each item.\n *\n * If 'obj' is an Object callback will be called passing\n * the value, key, and complete object for each property.\n *\n * @param {Object|Array} obj The object to iterate\n * @param {Function} fn The callback to invoke for each item\n */\nfunction forEach(obj, fn) {\n // Don't bother if no value provided\n if (obj === null || typeof obj === 'undefined') {\n return;\n }\n\n // Force an array if not already something iterable\n if (typeof obj !== 'object') {\n /*eslint no-param-reassign:0*/\n obj = [obj];\n }\n\n if (isArray(obj)) {\n // Iterate over array values\n for (var i = 0, l = obj.length; i < l; i++) {\n fn.call(null, obj[i], i, obj);\n }\n } else {\n // Iterate over object keys\n for (var key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n fn.call(null, obj[key], key, obj);\n }\n }\n }\n}\n\n/**\n * Accepts varargs expecting each argument to be an object, then\n * immutably merges the properties of each object and returns result.\n *\n * When multiple objects contain the same key the later object in\n * the arguments list will take precedence.\n *\n * Example:\n *\n * ```js\n * var result = merge({foo: 123}, {foo: 456});\n * console.log(result.foo); // outputs 456\n * ```\n *\n * @param {Object} obj1 Object to merge\n * @returns {Object} Result of all merge properties\n */\nfunction merge(/* obj1, obj2, obj3, ... */) {\n var result = {};\n function assignValue(val, key) {\n if (isPlainObject(result[key]) && isPlainObject(val)) {\n result[key] = merge(result[key], val);\n } else if (isPlainObject(val)) {\n result[key] = merge({}, val);\n } else if (isArray(val)) {\n result[key] = val.slice();\n } else {\n result[key] = val;\n }\n }\n\n for (var i = 0, l = arguments.length; i < l; i++) {\n forEach(arguments[i], assignValue);\n }\n return result;\n}\n\n/**\n * Extends object a by mutably adding to it the properties of object b.\n *\n * @param {Object} a The object to be extended\n * @param {Object} b The object to copy properties from\n * @param {Object} thisArg The object to bind function to\n * @return {Object} The resulting value of object a\n */\nfunction extend(a, b, thisArg) {\n forEach(b, function assignValue(val, key) {\n if (thisArg && typeof val === 'function') {\n a[key] = bind(val, thisArg);\n } else {\n a[key] = val;\n }\n });\n return a;\n}\n\n/**\n * Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)\n *\n * @param {string} content with BOM\n * @return {string} content value without BOM\n */\nfunction stripBOM(content) {\n if (content.charCodeAt(0) === 0xFEFF) {\n content = content.slice(1);\n }\n return content;\n}\n\n/**\n * Inherit the prototype methods from one constructor into another\n * @param {function} constructor\n * @param {function} superConstructor\n * @param {object} [props]\n * @param {object} [descriptors]\n */\n\nfunction inherits(constructor, superConstructor, props, descriptors) {\n constructor.prototype = Object.create(superConstructor.prototype, descriptors);\n constructor.prototype.constructor = constructor;\n props && Object.assign(constructor.prototype, props);\n}\n\n/**\n * Resolve object with deep prototype chain to a flat object\n * @param {Object} sourceObj source object\n * @param {Object} [destObj]\n * @param {Function} [filter]\n * @returns {Object}\n */\n\nfunction toFlatObject(sourceObj, destObj, filter) {\n var props;\n var i;\n var prop;\n var merged = {};\n\n destObj = destObj || {};\n\n do {\n props = Object.getOwnPropertyNames(sourceObj);\n i = props.length;\n while (i-- > 0) {\n prop = props[i];\n if (!merged[prop]) {\n destObj[prop] = sourceObj[prop];\n merged[prop] = true;\n }\n }\n sourceObj = Object.getPrototypeOf(sourceObj);\n } while (sourceObj && (!filter || filter(sourceObj, destObj)) && sourceObj !== Object.prototype);\n\n return destObj;\n}\n\n/*\n * determines whether a string ends with the characters of a specified string\n * @param {String} str\n * @param {String} searchString\n * @param {Number} [position= 0]\n * @returns {boolean}\n */\nfunction endsWith(str, searchString, position) {\n str = String(str);\n if (position === undefined || position > str.length) {\n position = str.length;\n }\n position -= searchString.length;\n var lastIndex = str.indexOf(searchString, position);\n return lastIndex !== -1 && lastIndex === position;\n}\n\n\n/**\n * Returns new array from array like object\n * @param {*} [thing]\n * @returns {Array}\n */\nfunction toArray(thing) {\n if (!thing) return null;\n var i = thing.length;\n if (isUndefined(i)) return null;\n var arr = new Array(i);\n while (i-- > 0) {\n arr[i] = thing[i];\n }\n return arr;\n}\n\n// eslint-disable-next-line func-names\nvar isTypedArray = (function(TypedArray) {\n // eslint-disable-next-line func-names\n return function(thing) {\n return TypedArray && thing instanceof TypedArray;\n };\n})(typeof Uint8Array !== 'undefined' && Object.getPrototypeOf(Uint8Array));\n\nmodule.exports = {\n isArray: isArray,\n isArrayBuffer: isArrayBuffer,\n isBuffer: isBuffer,\n isFormData: isFormData,\n isArrayBufferView: isArrayBufferView,\n isString: isString,\n isNumber: isNumber,\n isObject: isObject,\n isPlainObject: isPlainObject,\n isUndefined: isUndefined,\n isDate: isDate,\n isFile: isFile,\n isBlob: isBlob,\n isFunction: isFunction,\n isStream: isStream,\n isURLSearchParams: isURLSearchParams,\n isStandardBrowserEnv: isStandardBrowserEnv,\n forEach: forEach,\n merge: merge,\n extend: extend,\n trim: trim,\n stripBOM: stripBOM,\n inherits: inherits,\n toFlatObject: toFlatObject,\n kindOf: kindOf,\n kindOfTest: kindOfTest,\n endsWith: endsWith,\n toArray: toArray,\n isTypedArray: isTypedArray,\n isFileList: isFileList\n};\n","'use strict';\n\nvar utils = require('./../utils');\n\nfunction encode(val) {\n return encodeURIComponent(val).\n replace(/%3A/gi, ':').\n replace(/%24/g, '$').\n replace(/%2C/gi, ',').\n replace(/%20/g, '+').\n replace(/%5B/gi, '[').\n replace(/%5D/gi, ']');\n}\n\n/**\n * Build a URL by appending params to the end\n *\n * @param {string} url The base of the url (e.g., http://www.google.com)\n * @param {object} [params] The params to be appended\n * @returns {string} The formatted url\n */\nmodule.exports = function buildURL(url, params, paramsSerializer) {\n /*eslint no-param-reassign:0*/\n if (!params) {\n return url;\n }\n\n var serializedParams;\n if (paramsSerializer) {\n serializedParams = paramsSerializer(params);\n } else if (utils.isURLSearchParams(params)) {\n serializedParams = params.toString();\n } else {\n var parts = [];\n\n utils.forEach(params, function serialize(val, key) {\n if (val === null || typeof val === 'undefined') {\n return;\n }\n\n if (utils.isArray(val)) {\n key = key + '[]';\n } else {\n val = [val];\n }\n\n utils.forEach(val, function parseValue(v) {\n if (utils.isDate(v)) {\n v = v.toISOString();\n } else if (utils.isObject(v)) {\n v = JSON.stringify(v);\n }\n parts.push(encode(key) + '=' + encode(v));\n });\n });\n\n serializedParams = parts.join('&');\n }\n\n if (serializedParams) {\n var hashmarkIndex = url.indexOf('#');\n if (hashmarkIndex !== -1) {\n url = url.slice(0, hashmarkIndex);\n }\n\n url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams;\n }\n\n return url;\n};\n","'use strict';\n\nvar utils = require('./../utils');\n\nfunction InterceptorManager() {\n this.handlers = [];\n}\n\n/**\n * Add a new interceptor to the stack\n *\n * @param {Function} fulfilled The function to handle `then` for a `Promise`\n * @param {Function} rejected The function to handle `reject` for a `Promise`\n *\n * @return {Number} An ID used to remove interceptor later\n */\nInterceptorManager.prototype.use = function use(fulfilled, rejected, options) {\n this.handlers.push({\n fulfilled: fulfilled,\n rejected: rejected,\n synchronous: options ? options.synchronous : false,\n runWhen: options ? options.runWhen : null\n });\n return this.handlers.length - 1;\n};\n\n/**\n * Remove an interceptor from the stack\n *\n * @param {Number} id The ID that was returned by `use`\n */\nInterceptorManager.prototype.eject = function eject(id) {\n if (this.handlers[id]) {\n this.handlers[id] = null;\n }\n};\n\n/**\n * Iterate over all the registered interceptors\n *\n * This method is particularly useful for skipping over any\n * interceptors that may have become `null` calling `eject`.\n *\n * @param {Function} fn The function to call for each interceptor\n */\nInterceptorManager.prototype.forEach = function forEach(fn) {\n utils.forEach(this.handlers, function forEachHandler(h) {\n if (h !== null) {\n fn(h);\n }\n });\n};\n\nmodule.exports = InterceptorManager;\n","'use strict';\n\nvar utils = require('../utils');\n\nmodule.exports = function normalizeHeaderName(headers, normalizedName) {\n utils.forEach(headers, function processHeader(value, name) {\n if (name !== normalizedName && name.toUpperCase() === normalizedName.toUpperCase()) {\n headers[normalizedName] = value;\n delete headers[name];\n }\n });\n};\n","'use strict';\n\nvar utils = require('../utils');\n\n/**\n * Create an Error with the specified message, config, error code, request and response.\n *\n * @param {string} message The error message.\n * @param {string} [code] The error code (for example, 'ECONNABORTED').\n * @param {Object} [config] The config.\n * @param {Object} [request] The request.\n * @param {Object} [response] The response.\n * @returns {Error} The created error.\n */\nfunction AxiosError(message, code, config, request, response) {\n Error.call(this);\n this.message = message;\n this.name = 'AxiosError';\n code && (this.code = code);\n config && (this.config = config);\n request && (this.request = request);\n response && (this.response = response);\n}\n\nutils.inherits(AxiosError, Error, {\n toJSON: function toJSON() {\n return {\n // Standard\n message: this.message,\n name: this.name,\n // Microsoft\n description: this.description,\n number: this.number,\n // Mozilla\n fileName: this.fileName,\n lineNumber: this.lineNumber,\n columnNumber: this.columnNumber,\n stack: this.stack,\n // Axios\n config: this.config,\n code: this.code,\n status: this.response && this.response.status ? this.response.status : null\n };\n }\n});\n\nvar prototype = AxiosError.prototype;\nvar descriptors = {};\n\n[\n 'ERR_BAD_OPTION_VALUE',\n 'ERR_BAD_OPTION',\n 'ECONNABORTED',\n 'ETIMEDOUT',\n 'ERR_NETWORK',\n 'ERR_FR_TOO_MANY_REDIRECTS',\n 'ERR_DEPRECATED',\n 'ERR_BAD_RESPONSE',\n 'ERR_BAD_REQUEST',\n 'ERR_CANCELED'\n// eslint-disable-next-line func-names\n].forEach(function(code) {\n descriptors[code] = {value: code};\n});\n\nObject.defineProperties(AxiosError, descriptors);\nObject.defineProperty(prototype, 'isAxiosError', {value: true});\n\n// eslint-disable-next-line func-names\nAxiosError.from = function(error, code, config, request, response, customProps) {\n var axiosError = Object.create(prototype);\n\n utils.toFlatObject(error, axiosError, function filter(obj) {\n return obj !== Error.prototype;\n });\n\n AxiosError.call(axiosError, error.message, code, config, request, response);\n\n axiosError.name = error.name;\n\n customProps && Object.assign(axiosError, customProps);\n\n return axiosError;\n};\n\nmodule.exports = AxiosError;\n","'use strict';\n\nmodule.exports = {\n silentJSONParsing: true,\n forcedJSONParsing: true,\n clarifyTimeoutError: false\n};\n","'use strict';\n\nvar utils = require('../utils');\n\n/**\n * Convert a data object to FormData\n * @param {Object} obj\n * @param {?Object} [formData]\n * @returns {Object}\n **/\n\nfunction toFormData(obj, formData) {\n // eslint-disable-next-line no-param-reassign\n formData = formData || new FormData();\n\n var stack = [];\n\n function convertValue(value) {\n if (value === null) return '';\n\n if (utils.isDate(value)) {\n return value.toISOString();\n }\n\n if (utils.isArrayBuffer(value) || utils.isTypedArray(value)) {\n return typeof Blob === 'function' ? new Blob([value]) : Buffer.from(value);\n }\n\n return value;\n }\n\n function build(data, parentKey) {\n if (utils.isPlainObject(data) || utils.isArray(data)) {\n if (stack.indexOf(data) !== -1) {\n throw Error('Circular reference detected in ' + parentKey);\n }\n\n stack.push(data);\n\n utils.forEach(data, function each(value, key) {\n if (utils.isUndefined(value)) return;\n var fullKey = parentKey ? parentKey + '.' + key : key;\n var arr;\n\n if (value && !parentKey && typeof value === 'object') {\n if (utils.endsWith(key, '{}')) {\n // eslint-disable-next-line no-param-reassign\n value = JSON.stringify(value);\n } else if (utils.endsWith(key, '[]') && (arr = utils.toArray(value))) {\n // eslint-disable-next-line func-names\n arr.forEach(function(el) {\n !utils.isUndefined(el) && formData.append(fullKey, convertValue(el));\n });\n return;\n }\n }\n\n build(value, fullKey);\n });\n\n stack.pop();\n } else {\n formData.append(parentKey, convertValue(data));\n }\n }\n\n build(obj);\n\n return formData;\n}\n\nmodule.exports = toFormData;\n","'use strict';\n\nvar AxiosError = require('./AxiosError');\n\n/**\n * Resolve or reject a Promise based on response status.\n *\n * @param {Function} resolve A function that resolves the promise.\n * @param {Function} reject A function that rejects the promise.\n * @param {object} response The response.\n */\nmodule.exports = function settle(resolve, reject, response) {\n var validateStatus = response.config.validateStatus;\n if (!response.status || !validateStatus || validateStatus(response.status)) {\n resolve(response);\n } else {\n reject(new AxiosError(\n 'Request failed with status code ' + response.status,\n [AxiosError.ERR_BAD_REQUEST, AxiosError.ERR_BAD_RESPONSE][Math.floor(response.status / 100) - 4],\n response.config,\n response.request,\n response\n ));\n }\n};\n","'use strict';\n\nvar utils = require('./../utils');\n\nmodule.exports = (\n utils.isStandardBrowserEnv() ?\n\n // Standard browser envs support document.cookie\n (function standardBrowserEnv() {\n return {\n write: function write(name, value, expires, path, domain, secure) {\n var cookie = [];\n cookie.push(name + '=' + encodeURIComponent(value));\n\n if (utils.isNumber(expires)) {\n cookie.push('expires=' + new Date(expires).toGMTString());\n }\n\n if (utils.isString(path)) {\n cookie.push('path=' + path);\n }\n\n if (utils.isString(domain)) {\n cookie.push('domain=' + domain);\n }\n\n if (secure === true) {\n cookie.push('secure');\n }\n\n document.cookie = cookie.join('; ');\n },\n\n read: function read(name) {\n var match = document.cookie.match(new RegExp('(^|;\\\\s*)(' + name + ')=([^;]*)'));\n return (match ? decodeURIComponent(match[3]) : null);\n },\n\n remove: function remove(name) {\n this.write(name, '', Date.now() - 86400000);\n }\n };\n })() :\n\n // Non standard browser env (web workers, react-native) lack needed support.\n (function nonStandardBrowserEnv() {\n return {\n write: function write() {},\n read: function read() { return null; },\n remove: function remove() {}\n };\n })()\n);\n","'use strict';\n\n/**\n * Determines whether the specified URL is absolute\n *\n * @param {string} url The URL to test\n * @returns {boolean} True if the specified URL is absolute, otherwise false\n */\nmodule.exports = function isAbsoluteURL(url) {\n // A URL is considered absolute if it begins with \"<scheme>://\" or \"//\" (protocol-relative URL).\n // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed\n // by any combination of letters, digits, plus, period, or hyphen.\n return /^([a-z][a-z\\d+\\-.]*:)?\\/\\//i.test(url);\n};\n","'use strict';\n\n/**\n * Creates a new URL by combining the specified URLs\n *\n * @param {string} baseURL The base URL\n * @param {string} relativeURL The relative URL\n * @returns {string} The combined URL\n */\nmodule.exports = function combineURLs(baseURL, relativeURL) {\n return relativeURL\n ? baseURL.replace(/\\/+$/, '') + '/' + relativeURL.replace(/^\\/+/, '')\n : baseURL;\n};\n","'use strict';\n\nvar isAbsoluteURL = require('../helpers/isAbsoluteURL');\nvar combineURLs = require('../helpers/combineURLs');\n\n/**\n * Creates a new URL by combining the baseURL with the requestedURL,\n * only when the requestedURL is not already an absolute URL.\n * If the requestURL is absolute, this function returns the requestedURL untouched.\n *\n * @param {string} baseURL The base URL\n * @param {string} requestedURL Absolute or relative URL to combine\n * @returns {string} The combined full path\n */\nmodule.exports = function buildFullPath(baseURL, requestedURL) {\n if (baseURL && !isAbsoluteURL(requestedURL)) {\n return combineURLs(baseURL, requestedURL);\n }\n return requestedURL;\n};\n","'use strict';\n\nvar utils = require('./../utils');\n\n// Headers whose duplicates are ignored by node\n// c.f. https://nodejs.org/api/http.html#http_message_headers\nvar ignoreDuplicateOf = [\n 'age', 'authorization', 'content-length', 'content-type', 'etag',\n 'expires', 'from', 'host', 'if-modified-since', 'if-unmodified-since',\n 'last-modified', 'location', 'max-forwards', 'proxy-authorization',\n 'referer', 'retry-after', 'user-agent'\n];\n\n/**\n * Parse headers into an object\n *\n * ```\n * Date: Wed, 27 Aug 2014 08:58:49 GMT\n * Content-Type: application/json\n * Connection: keep-alive\n * Transfer-Encoding: chunked\n * ```\n *\n * @param {String} headers Headers needing to be parsed\n * @returns {Object} Headers parsed into an object\n */\nmodule.exports = function parseHeaders(headers) {\n var parsed = {};\n var key;\n var val;\n var i;\n\n if (!headers) { return parsed; }\n\n utils.forEach(headers.split('\\n'), function parser(line) {\n i = line.indexOf(':');\n key = utils.trim(line.substr(0, i)).toLowerCase();\n val = utils.trim(line.substr(i + 1));\n\n if (key) {\n if (parsed[key] && ignoreDuplicateOf.indexOf(key) >= 0) {\n return;\n }\n if (key === 'set-cookie') {\n parsed[key] = (parsed[key] ? parsed[key] : []).concat([val]);\n } else {\n parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;\n }\n }\n });\n\n return parsed;\n};\n","'use strict';\n\nvar utils = require('./../utils');\n\nmodule.exports = (\n utils.isStandardBrowserEnv() ?\n\n // Standard browser envs have full support of the APIs needed to test\n // whether the request URL is of the same origin as current location.\n (function standardBrowserEnv() {\n var msie = /(msie|trident)/i.test(navigator.userAgent);\n var urlParsingNode = document.createElement('a');\n var originURL;\n\n /**\n * Parse a URL to discover it's components\n *\n * @param {String} url The URL to be parsed\n * @returns {Object}\n */\n function resolveURL(url) {\n var href = url;\n\n if (msie) {\n // IE needs attribute set twice to normalize properties\n urlParsingNode.setAttribute('href', href);\n href = urlParsingNode.href;\n }\n\n urlParsingNode.setAttribute('href', href);\n\n // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils\n return {\n href: urlParsingNode.href,\n protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',\n host: urlParsingNode.host,\n search: urlParsingNode.search ? urlParsingNode.search.replace(/^\\?/, '') : '',\n hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',\n hostname: urlParsingNode.hostname,\n port: urlParsingNode.port,\n pathname: (urlParsingNode.pathname.charAt(0) === '/') ?\n urlParsingNode.pathname :\n '/' + urlParsingNode.pathname\n };\n }\n\n originURL = resolveURL(window.location.href);\n\n /**\n * Determine if a URL shares the same origin as the current location\n *\n * @param {String} requestURL The URL to test\n * @returns {boolean} True if URL shares the same origin, otherwise false\n */\n return function isURLSameOrigin(requestURL) {\n var parsed = (utils.isString(requestURL)) ? resolveURL(requestURL) : requestURL;\n return (parsed.protocol === originURL.protocol &&\n parsed.host === originURL.host);\n };\n })() :\n\n // Non standard browser envs (web workers, react-native) lack needed support.\n (function nonStandardBrowserEnv() {\n return function isURLSameOrigin() {\n return true;\n };\n })()\n);\n","'use strict';\n\nvar AxiosError = require('../core/AxiosError');\nvar utils = require('../utils');\n\n/**\n * A `CanceledError` is an object that is thrown when an operation is canceled.\n *\n * @class\n * @param {string=} message The message.\n */\nfunction CanceledError(message) {\n // eslint-disable-next-line no-eq-null,eqeqeq\n AxiosError.call(this, message == null ? 'canceled' : message, AxiosError.ERR_CANCELED);\n this.name = 'CanceledError';\n}\n\nutils.inherits(CanceledError, AxiosError, {\n __CANCEL__: true\n});\n\nmodule.exports = CanceledError;\n","'use strict';\n\nmodule.exports = function parseProtocol(url) {\n var match = /^([-+\\w]{1,25})(:?\\/\\/|:)/.exec(url);\n return match && match[1] || '';\n};\n","'use strict';\n\nvar utils = require('./../utils');\nvar settle = require('./../core/settle');\nvar cookies = require('./../helpers/cookies');\nvar buildURL = require('./../helpers/buildURL');\nvar buildFullPath = require('../core/buildFullPath');\nvar parseHeaders = require('./../helpers/parseHeaders');\nvar isURLSameOrigin = require('./../helpers/isURLSameOrigin');\nvar transitionalDefaults = require('../defaults/transitional');\nvar AxiosError = require('../core/AxiosError');\nvar CanceledError = require('../cancel/CanceledError');\nvar parseProtocol = require('../helpers/parseProtocol');\n\nmodule.exports = function xhrAdapter(config) {\n return new Promise(function dispatchXhrRequest(resolve, reject) {\n var requestData = config.data;\n var requestHeaders = config.headers;\n var responseType = config.responseType;\n var onCanceled;\n function done() {\n if (config.cancelToken) {\n config.cancelToken.unsubscribe(onCanceled);\n }\n\n if (config.signal) {\n config.signal.removeEventListener('abort', onCanceled);\n }\n }\n\n if (utils.isFormData(requestData) && utils.isStandardBrowserEnv()) {\n delete requestHeaders['Content-Type']; // Let the browser set it\n }\n\n var request = new XMLHttpRequest();\n\n // HTTP basic authentication\n if (config.auth) {\n var username = config.auth.username || '';\n var password = config.auth.password ? unescape(encodeURIComponent(config.auth.password)) : '';\n requestHeaders.Authorization = 'Basic ' + btoa(username + ':' + password);\n }\n\n var fullPath = buildFullPath(config.baseURL, config.url);\n\n request.open(config.method.toUpperCase(), buildURL(fullPath, config.params, config.paramsSerializer), true);\n\n // Set the request timeout in MS\n request.timeout = config.timeout;\n\n function onloadend() {\n if (!request) {\n return;\n }\n // Prepare the response\n var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null;\n var responseData = !responseType || responseType === 'text' || responseType === 'json' ?\n request.responseText : request.response;\n var response = {\n data: responseData,\n status: request.status,\n statusText: request.statusText,\n headers: responseHeaders,\n config: config,\n request: request\n };\n\n settle(function _resolve(value) {\n resolve(value);\n done();\n }, function _reject(err) {\n reject(err);\n done();\n }, response);\n\n // Clean up request\n request = null;\n }\n\n if ('onloadend' in request) {\n // Use onloadend if available\n request.onloadend = onloadend;\n } else {\n // Listen for ready state to emulate onloadend\n request.onreadystatechange = function handleLoad() {\n if (!request || request.readyState !== 4) {\n return;\n }\n\n // The request errored out and we didn't get a response, this will be\n // handled by onerror instead\n // With one exception: request that using file: protocol, most browsers\n // will return status as 0 even though it's a successful request\n if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) {\n return;\n }\n // readystate handler is calling before onerror or ontimeout handlers,\n // so we should call onloadend on the next 'tick'\n setTimeout(onloadend);\n };\n }\n\n // Handle browser request cancellation (as opposed to a manual cancellation)\n request.onabort = function handleAbort() {\n if (!request) {\n return;\n }\n\n reject(new AxiosError('Request aborted', AxiosError.ECONNABORTED, config, request));\n\n // Clean up request\n request = null;\n };\n\n // Handle low level network errors\n request.onerror = function handleError() {\n // Real errors are hidden from us by the browser\n // onerror should only fire if it's a network error\n reject(new AxiosError('Network Error', AxiosError.ERR_NETWORK, config, request, request));\n\n // Clean up request\n request = null;\n };\n\n // Handle timeout\n request.ontimeout = function handleTimeout() {\n var timeoutErrorMessage = config.timeout ? 'timeout of ' + config.timeout + 'ms exceeded' : 'timeout exceeded';\n var transitional = config.transitional || transitionalDefaults;\n if (config.timeoutErrorMessage) {\n timeoutErrorMessage = config.timeoutErrorMessage;\n }\n reject(new AxiosError(\n timeoutErrorMessage,\n transitional.clarifyTimeoutError ? AxiosError.ETIMEDOUT : AxiosError.ECONNABORTED,\n config,\n request));\n\n // Clean up request\n request = null;\n };\n\n // Add xsrf header\n // This is only done if running in a standard browser environment.\n // Specifically not if we're in a web worker, or react-native.\n if (utils.isStandardBrowserEnv()) {\n // Add xsrf header\n var xsrfValue = (config.withCredentials || isURLSameOrigin(fullPath)) && config.xsrfCookieName ?\n cookies.read(config.xsrfCookieName) :\n undefined;\n\n if (xsrfValue) {\n requestHeaders[config.xsrfHeaderName] = xsrfValue;\n }\n }\n\n // Add headers to the request\n if ('setRequestHeader' in request) {\n utils.forEach(requestHeaders, function setRequestHeader(val, key) {\n if (typeof requestData === 'undefined' && key.toLowerCase() === 'content-type') {\n // Remove Content-Type if data is undefined\n delete requestHeaders[key];\n } else {\n // Otherwise add header to the request\n request.setRequestHeader(key, val);\n }\n });\n }\n\n // Add withCredentials to request if needed\n if (!utils.isUndefined(config.withCredentials)) {\n request.withCredentials = !!config.withCredentials;\n }\n\n // Add responseType to request if needed\n if (responseType && responseType !== 'json') {\n request.responseType = config.responseType;\n }\n\n // Handle progress if needed\n if (typeof config.onDownloadProgress === 'function') {\n request.addEventListener('progress', config.onDownloadProgress);\n }\n\n // Not all browsers support upload events\n if (typeof config.onUploadProgress === 'function' && request.upload) {\n request.upload.addEventListener('progress', config.onUploadProgress);\n }\n\n if (config.cancelToken || config.signal) {\n // Handle cancellation\n // eslint-disable-next-line func-names\n onCanceled = function(cancel) {\n if (!request) {\n return;\n }\n reject(!cancel || (cancel && cancel.type) ? new CanceledError() : cancel);\n request.abort();\n request = null;\n };\n\n config.cancelToken && config.cancelToken.subscribe(onCanceled);\n if (config.signal) {\n config.signal.aborted ? onCanceled() : config.signal.addEventListener('abort', onCanceled);\n }\n }\n\n if (!requestData) {\n requestData = null;\n }\n\n var protocol = parseProtocol(fullPath);\n\n if (protocol && [ 'http', 'https', 'file' ].indexOf(protocol) === -1) {\n reject(new AxiosError('Unsupported protocol ' + protocol + ':', AxiosError.ERR_BAD_REQUEST, config));\n return;\n }\n\n\n // Send the request\n request.send(requestData);\n });\n};\n","// eslint-disable-next-line strict\nmodule.exports = null;\n","'use strict';\n\nvar utils = require('../utils');\nvar normalizeHeaderName = require('../helpers/normalizeHeaderName');\nvar AxiosError = require('../core/AxiosError');\nvar transitionalDefaults = require('./transitional');\nvar toFormData = require('../helpers/toFormData');\n\nvar DEFAULT_CONTENT_TYPE = {\n 'Content-Type': 'application/x-www-form-urlencoded'\n};\n\nfunction setContentTypeIfUnset(headers, value) {\n if (!utils.isUndefined(headers) && utils.isUndefined(headers['Content-Type'])) {\n headers['Content-Type'] = value;\n }\n}\n\nfunction getDefaultAdapter() {\n var adapter;\n if (typeof XMLHttpRequest !== 'undefined') {\n // For browsers use XHR adapter\n adapter = require('../adapters/xhr');\n } else if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') {\n // For node use HTTP adapter\n adapter = require('../adapters/http');\n }\n return adapter;\n}\n\nfunction stringifySafely(rawValue, parser, encoder) {\n if (utils.isString(rawValue)) {\n try {\n (parser || JSON.parse)(rawValue);\n return utils.trim(rawValue);\n } catch (e) {\n if (e.name !== 'SyntaxError') {\n throw e;\n }\n }\n }\n\n return (encoder || JSON.stringify)(rawValue);\n}\n\nvar defaults = {\n\n transitional: transitionalDefaults,\n\n adapter: getDefaultAdapter(),\n\n transformRequest: [function transformRequest(data, headers) {\n normalizeHeaderName(headers, 'Accept');\n normalizeHeaderName(headers, 'Content-Type');\n\n if (utils.isFormData(data) ||\n utils.isArrayBuffer(data) ||\n utils.isBuffer(data) ||\n utils.isStream(data) ||\n utils.isFile(data) ||\n utils.isBlob(data)\n ) {\n return data;\n }\n if (utils.isArrayBufferView(data)) {\n return data.buffer;\n }\n if (utils.isURLSearchParams(data)) {\n setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8');\n return data.toString();\n }\n\n var isObjectPayload = utils.isObject(data);\n var contentType = headers && headers['Content-Type'];\n\n var isFileList;\n\n if ((isFileList = utils.isFileList(data)) || (isObjectPayload && contentType === 'multipart/form-data')) {\n var _FormData = this.env && this.env.FormData;\n return toFormData(isFileList ? {'files[]': data} : data, _FormData && new _FormData());\n } else if (isObjectPayload || contentType === 'application/json') {\n setContentTypeIfUnset(headers, 'application/json');\n return stringifySafely(data);\n }\n\n return data;\n }],\n\n transformResponse: [function transformResponse(data) {\n var transitional = this.transitional || defaults.transitional;\n var silentJSONParsing = transitional && transitional.silentJSONParsing;\n var forcedJSONParsing = transitional && transitional.forcedJSONParsing;\n var strictJSONParsing = !silentJSONParsing && this.responseType === 'json';\n\n if (strictJSONParsing || (forcedJSONParsing && utils.isString(data) && data.length)) {\n try {\n return JSON.parse(data);\n } catch (e) {\n if (strictJSONParsing) {\n if (e.name === 'SyntaxError') {\n throw AxiosError.from(e, AxiosError.ERR_BAD_RESPONSE, this, null, this.response);\n }\n throw e;\n }\n }\n }\n\n return data;\n }],\n\n /**\n * A timeout in milliseconds to abort a request. If set to 0 (default) a\n * timeout is not created.\n */\n timeout: 0,\n\n xsrfCookieName: 'XSRF-TOKEN',\n xsrfHeaderName: 'X-XSRF-TOKEN',\n\n maxContentLength: -1,\n maxBodyLength: -1,\n\n env: {\n FormData: require('./env/FormData')\n },\n\n validateStatus: function validateStatus(status) {\n return status >= 200 && status < 300;\n },\n\n headers: {\n common: {\n 'Accept': 'application/json, text/plain, */*'\n }\n }\n};\n\nutils.forEach(['delete', 'get', 'head'], function forEachMethodNoData(method) {\n defaults.headers[method] = {};\n});\n\nutils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {\n defaults.headers[method] = utils.merge(DEFAULT_CONTENT_TYPE);\n});\n\nmodule.exports = defaults;\n","'use strict';\n\nvar utils = require('./../utils');\nvar defaults = require('../defaults');\n\n/**\n * Transform the data for a request or a response\n *\n * @param {Object|String} data The data to be transformed\n * @param {Array} headers The headers for the request or response\n * @param {Array|Function} fns A single function or Array of functions\n * @returns {*} The resulting transformed data\n */\nmodule.exports = function transformData(data, headers, fns) {\n var context = this || defaults;\n /*eslint no-param-reassign:0*/\n utils.forEach(fns, function transform(fn) {\n data = fn.call(context, data, headers);\n });\n\n return data;\n};\n","'use strict';\n\nmodule.exports = function isCancel(value) {\n return !!(value && value.__CANCEL__);\n};\n","'use strict';\n\nvar utils = require('./../utils');\nvar transformData = require('./transformData');\nvar isCancel = require('../cancel/isCancel');\nvar defaults = require('../defaults');\nvar CanceledError = require('../cancel/CanceledError');\n\n/**\n * Throws a `CanceledError` if cancellation has been requested.\n */\nfunction throwIfCancellationRequested(config) {\n if (config.cancelToken) {\n config.cancelToken.throwIfRequested();\n }\n\n if (config.signal && config.signal.aborted) {\n throw new CanceledError();\n }\n}\n\n/**\n * Dispatch a request to the server using the configured adapter.\n *\n * @param {object} config The config that is to be used for the request\n * @returns {Promise} The Promise to be fulfilled\n */\nmodule.exports = function dispatchRequest(config) {\n throwIfCancellationRequested(config);\n\n // Ensure headers exist\n config.headers = config.headers || {};\n\n // Transform request data\n config.data = transformData.call(\n config,\n config.data,\n config.headers,\n config.transformRequest\n );\n\n // Flatten headers\n config.headers = utils.merge(\n config.headers.common || {},\n config.headers[config.method] || {},\n config.headers\n );\n\n utils.forEach(\n ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'],\n function cleanHeaderConfig(method) {\n delete config.headers[method];\n }\n );\n\n var adapter = config.adapter || defaults.adapter;\n\n return adapter(config).then(function onAdapterResolution(response) {\n throwIfCancellationRequested(config);\n\n // Transform response data\n response.data = transformData.call(\n config,\n response.data,\n response.headers,\n config.transformResponse\n );\n\n return response;\n }, function onAdapterRejection(reason) {\n if (!isCancel(reason)) {\n throwIfCancellationRequested(config);\n\n // Transform response data\n if (reason && reason.response) {\n reason.response.data = transformData.call(\n config,\n reason.response.data,\n reason.response.headers,\n config.transformResponse\n );\n }\n }\n\n return Promise.reject(reason);\n });\n};\n","'use strict';\n\nvar utils = require('../utils');\n\n/**\n * Config-specific merge-function which creates a new config-object\n * by merging two configuration objects together.\n *\n * @param {Object} config1\n * @param {Object} config2\n * @returns {Object} New object resulting from merging config2 to config1\n */\nmodule.exports = function mergeConfig(config1, config2) {\n // eslint-disable-next-line no-param-reassign\n config2 = config2 || {};\n var config = {};\n\n function getMergedValue(target, source) {\n if (utils.isPlainObject(target) && utils.isPlainObject(source)) {\n return utils.merge(target, source);\n } else if (utils.isPlainObject(source)) {\n return utils.merge({}, source);\n } else if (utils.isArray(source)) {\n return source.slice();\n }\n return source;\n }\n\n // eslint-disable-next-line consistent-return\n function mergeDeepProperties(prop) {\n if (!utils.isUndefined(config2[prop])) {\n return getMergedValue(config1[prop], config2[prop]);\n } else if (!utils.isUndefined(config1[prop])) {\n return getMergedValue(undefined, config1[prop]);\n }\n }\n\n // eslint-disable-next-line consistent-return\n function valueFromConfig2(prop) {\n if (!utils.isUndefined(config2[prop])) {\n return getMergedValue(undefined, config2[prop]);\n }\n }\n\n // eslint-disable-next-line consistent-return\n function defaultToConfig2(prop) {\n if (!utils.isUndefined(config2[prop])) {\n return getMergedValue(undefined, config2[prop]);\n } else if (!utils.isUndefined(config1[prop])) {\n return getMergedValue(undefined, config1[prop]);\n }\n }\n\n // eslint-disable-next-line consistent-return\n function mergeDirectKeys(prop) {\n if (prop in config2) {\n return getMergedValue(config1[prop], config2[prop]);\n } else if (prop in config1) {\n return getMergedValue(undefined, config1[prop]);\n }\n }\n\n var mergeMap = {\n 'url': valueFromConfig2,\n 'method': valueFromConfig2,\n 'data': valueFromConfig2,\n 'baseURL': defaultToConfig2,\n 'transformRequest': defaultToConfig2,\n 'transformResponse': defaultToConfig2,\n 'paramsSerializer': defaultToConfig2,\n 'timeout': defaultToConfig2,\n 'timeoutMessage': defaultToConfig2,\n 'withCredentials': defaultToConfig2,\n 'adapter': defaultToConfig2,\n 'responseType': defaultToConfig2,\n 'xsrfCookieName': defaultToConfig2,\n 'xsrfHeaderName': defaultToConfig2,\n 'onUploadProgress': defaultToConfig2,\n 'onDownloadProgress': defaultToConfig2,\n 'decompress': defaultToConfig2,\n 'maxContentLength': defaultToConfig2,\n 'maxBodyLength': defaultToConfig2,\n 'beforeRedirect': defaultToConfig2,\n 'transport': defaultToConfig2,\n 'httpAgent': defaultToConfig2,\n 'httpsAgent': defaultToConfig2,\n 'cancelToken': defaultToConfig2,\n 'socketPath': defaultToConfig2,\n 'responseEncoding': defaultToConfig2,\n 'validateStatus': mergeDirectKeys\n };\n\n utils.forEach(Object.keys(config1).concat(Object.keys(config2)), function computeConfigValue(prop) {\n var merge = mergeMap[prop] || mergeDeepProperties;\n var configValue = merge(prop);\n (utils.isUndefined(configValue) && merge !== mergeDirectKeys) || (config[prop] = configValue);\n });\n\n return config;\n};\n","module.exports = {\n \"version\": \"0.27.2\"\n};","'use strict';\n\nvar VERSION = require('../env/data').version;\nvar AxiosError = require('../core/AxiosError');\n\nvar validators = {};\n\n// eslint-disable-next-line func-names\n['object', 'boolean', 'number', 'function', 'string', 'symbol'].forEach(function(type, i) {\n validators[type] = function validator(thing) {\n return typeof thing === type || 'a' + (i < 1 ? 'n ' : ' ') + type;\n };\n});\n\nvar deprecatedWarnings = {};\n\n/**\n * Transitional option validator\n * @param {function|boolean?} validator - set to false if the transitional option has been removed\n * @param {string?} version - deprecated version / removed since version\n * @param {string?} message - some message with additional info\n * @returns {function}\n */\nvalidators.transitional = function transitional(validator, version, message) {\n function formatMessage(opt, desc) {\n return '[Axios v' + VERSION + '] Transitional option \\'' + opt + '\\'' + desc + (message ? '. ' + message : '');\n }\n\n // eslint-disable-next-line func-names\n return function(value, opt, opts) {\n if (validator === false) {\n throw new AxiosError(\n formatMessage(opt, ' has been removed' + (version ? ' in ' + version : '')),\n AxiosError.ERR_DEPRECATED\n );\n }\n\n if (version && !deprecatedWarnings[opt]) {\n deprecatedWarnings[opt] = true;\n // eslint-disable-next-line no-console\n console.warn(\n formatMessage(\n opt,\n ' has been deprecated since v' + version + ' and will be removed in the near future'\n )\n );\n }\n\n return validator ? validator(value, opt, opts) : true;\n };\n};\n\n/**\n * Assert object's properties type\n * @param {object} options\n * @param {object} schema\n * @param {boolean?} allowUnknown\n */\n\nfunction assertOptions(options, schema, allowUnknown) {\n if (typeof options !== 'object') {\n throw new AxiosError('options must be an object', AxiosError.ERR_BAD_OPTION_VALUE);\n }\n var keys = Object.keys(options);\n var i = keys.length;\n while (i-- > 0) {\n var opt = keys[i];\n var validator = schema[opt];\n if (validator) {\n var value = options[opt];\n var result = value === undefined || validator(value, opt, options);\n if (result !== true) {\n throw new AxiosError('option ' + opt + ' must be ' + result, AxiosError.ERR_BAD_OPTION_VALUE);\n }\n continue;\n }\n if (allowUnknown !== true) {\n throw new AxiosError('Unknown option ' + opt, AxiosError.ERR_BAD_OPTION);\n }\n }\n}\n\nmodule.exports = {\n assertOptions: assertOptions,\n validators: validators\n};\n","'use strict';\n\nvar utils = require('./../utils');\nvar buildURL = require('../helpers/buildURL');\nvar InterceptorManager = require('./InterceptorManager');\nvar dispatchRequest = require('./dispatchRequest');\nvar mergeConfig = require('./mergeConfig');\nvar buildFullPath = require('./buildFullPath');\nvar validator = require('../helpers/validator');\n\nvar validators = validator.validators;\n/**\n * Create a new instance of Axios\n *\n * @param {Object} instanceConfig The default config for the instance\n */\nfunction Axios(instanceConfig) {\n this.defaults = instanceConfig;\n this.interceptors = {\n request: new InterceptorManager(),\n response: new InterceptorManager()\n };\n}\n\n/**\n * Dispatch a request\n *\n * @param {Object} config The config specific for this request (merged with this.defaults)\n */\nAxios.prototype.request = function request(configOrUrl, config) {\n /*eslint no-param-reassign:0*/\n // Allow for axios('example/url'[, config]) a la fetch API\n if (typeof configOrUrl === 'string') {\n config = config || {};\n config.url = configOrUrl;\n } else {\n config = configOrUrl || {};\n }\n\n config = mergeConfig(this.defaults, config);\n\n // Set config.method\n if (config.method) {\n config.method = config.method.toLowerCase();\n } else if (this.defaults.method) {\n config.method = this.defaults.method.toLowerCase();\n } else {\n config.method = 'get';\n }\n\n var transitional = config.transitional;\n\n if (transitional !== undefined) {\n validator.assertOptions(transitional, {\n silentJSONParsing: validators.transitional(validators.boolean),\n forcedJSONParsing: validators.transitional(validators.boolean),\n clarifyTimeoutError: validators.transitional(validators.boolean)\n }, false);\n }\n\n // filter out skipped interceptors\n var requestInterceptorChain = [];\n var synchronousRequestInterceptors = true;\n this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {\n if (typeof interceptor.runWhen === 'function' && interceptor.runWhen(config) === false) {\n return;\n }\n\n synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous;\n\n requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);\n });\n\n var responseInterceptorChain = [];\n this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {\n responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected);\n });\n\n var promise;\n\n if (!synchronousRequestInterceptors) {\n var chain = [dispatchRequest, undefined];\n\n Array.prototype.unshift.apply(chain, requestInterceptorChain);\n chain = chain.concat(responseInterceptorChain);\n\n promise = Promise.resolve(config);\n while (chain.length) {\n promise = promise.then(chain.shift(), chain.shift());\n }\n\n return promise;\n }\n\n\n var newConfig = config;\n while (requestInterceptorChain.length) {\n var onFulfilled = requestInterceptorChain.shift();\n var onRejected = requestInterceptorChain.shift();\n try {\n newConfig = onFulfilled(newConfig);\n } catch (error) {\n onRejected(error);\n break;\n }\n }\n\n try {\n promise = dispatchRequest(newConfig);\n } catch (error) {\n return Promise.reject(error);\n }\n\n while (responseInterceptorChain.length) {\n promise = promise.then(responseInterceptorChain.shift(), responseInterceptorChain.shift());\n }\n\n return promise;\n};\n\nAxios.prototype.getUri = function getUri(config) {\n config = mergeConfig(this.defaults, config);\n var fullPath = buildFullPath(config.baseURL, config.url);\n return buildURL(fullPath, config.params, config.paramsSerializer);\n};\n\n// Provide aliases for supported request methods\nutils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {\n /*eslint func-names:0*/\n Axios.prototype[method] = function(url, config) {\n return this.request(mergeConfig(config || {}, {\n method: method,\n url: url,\n data: (config || {}).data\n }));\n };\n});\n\nutils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {\n /*eslint func-names:0*/\n\n function generateHTTPMethod(isForm) {\n return function httpMethod(url, data, config) {\n return this.request(mergeConfig(config || {}, {\n method: method,\n headers: isForm ? {\n 'Content-Type': 'multipart/form-data'\n } : {},\n url: url,\n data: data\n }));\n };\n }\n\n Axios.prototype[method] = generateHTTPMethod();\n\n Axios.prototype[method + 'Form'] = generateHTTPMethod(true);\n});\n\nmodule.exports = Axios;\n","'use strict';\n\nvar CanceledError = require('./CanceledError');\n\n/**\n * A `CancelToken` is an object that can be used to request cancellation of an operation.\n *\n * @class\n * @param {Function} executor The executor function.\n */\nfunction CancelToken(executor) {\n if (typeof executor !== 'function') {\n throw new TypeError('executor must be a function.');\n }\n\n var resolvePromise;\n\n this.promise = new Promise(function promiseExecutor(resolve) {\n resolvePromise = resolve;\n });\n\n var token = this;\n\n // eslint-disable-next-line func-names\n this.promise.then(function(cancel) {\n if (!token._listeners) return;\n\n var i;\n var l = token._listeners.length;\n\n for (i = 0; i < l; i++) {\n token._listeners[i](cancel);\n }\n token._listeners = null;\n });\n\n // eslint-disable-next-line func-names\n this.promise.then = function(onfulfilled) {\n var _resolve;\n // eslint-disable-next-line func-names\n var promise = new Promise(function(resolve) {\n token.subscribe(resolve);\n _resolve = resolve;\n }).then(onfulfilled);\n\n promise.cancel = function reject() {\n token.unsubscribe(_resolve);\n };\n\n return promise;\n };\n\n executor(function cancel(message) {\n if (token.reason) {\n // Cancellation has already been requested\n return;\n }\n\n token.reason = new CanceledError(message);\n resolvePromise(token.reason);\n });\n}\n\n/**\n * Throws a `CanceledError` if cancellation has been requested.\n */\nCancelToken.prototype.throwIfRequested = function throwIfRequested() {\n if (this.reason) {\n throw this.reason;\n }\n};\n\n/**\n * Subscribe to the cancel signal\n */\n\nCancelToken.prototype.subscribe = function subscribe(listener) {\n if (this.reason) {\n listener(this.reason);\n return;\n }\n\n if (this._listeners) {\n this._listeners.push(listener);\n } else {\n this._listeners = [listener];\n }\n};\n\n/**\n * Unsubscribe from the cancel signal\n */\n\nCancelToken.prototype.unsubscribe = function unsubscribe(listener) {\n if (!this._listeners) {\n return;\n }\n var index = this._listeners.indexOf(listener);\n if (index !== -1) {\n this._listeners.splice(index, 1);\n }\n};\n\n/**\n * Returns an object that contains a new `CancelToken` and a function that, when called,\n * cancels the `CancelToken`.\n */\nCancelToken.source = function source() {\n var cancel;\n var token = new CancelToken(function executor(c) {\n cancel = c;\n });\n return {\n token: token,\n cancel: cancel\n };\n};\n\nmodule.exports = CancelToken;\n","'use strict';\n\n/**\n * Syntactic sugar for invoking a function and expanding an array for arguments.\n *\n * Common use case would be to use `Function.prototype.apply`.\n *\n * ```js\n * function f(x, y, z) {}\n * var args = [1, 2, 3];\n * f.apply(null, args);\n * ```\n *\n * With `spread` this example can be re-written.\n *\n * ```js\n * spread(function(x, y, z) {})([1, 2, 3]);\n * ```\n *\n * @param {Function} callback\n * @returns {Function}\n */\nmodule.exports = function spread(callback) {\n return function wrap(arr) {\n return callback.apply(null, arr);\n };\n};\n","'use strict';\n\nvar utils = require('./../utils');\n\n/**\n * Determines whether the payload is an error thrown by Axios\n *\n * @param {*} payload The value to test\n * @returns {boolean} True if the payload is an error thrown by Axios, otherwise false\n */\nmodule.exports = function isAxiosError(payload) {\n return utils.isObject(payload) && (payload.isAxiosError === true);\n};\n","'use strict';\n\nvar utils = require('./utils');\nvar bind = require('./helpers/bind');\nvar Axios = require('./core/Axios');\nvar mergeConfig = require('./core/mergeConfig');\nvar defaults = require('./defaults');\n\n/**\n * Create an instance of Axios\n *\n * @param {Object} defaultConfig The default config for the instance\n * @return {Axios} A new instance of Axios\n */\nfunction createInstance(defaultConfig) {\n var context = new Axios(defaultConfig);\n var instance = bind(Axios.prototype.request, context);\n\n // Copy axios.prototype to instance\n utils.extend(instance, Axios.prototype, context);\n\n // Copy context to instance\n utils.extend(instance, context);\n\n // Factory for creating new instances\n instance.create = function create(instanceConfig) {\n return createInstance(mergeConfig(defaultConfig, instanceConfig));\n };\n\n return instance;\n}\n\n// Create the default instance to be exported\nvar axios = createInstance(defaults);\n\n// Expose Axios class to allow class inheritance\naxios.Axios = Axios;\n\n// Expose Cancel & CancelToken\naxios.CanceledError = require('./cancel/CanceledError');\naxios.CancelToken = require('./cancel/CancelToken');\naxios.isCancel = require('./cancel/isCancel');\naxios.VERSION = require('./env/data').version;\naxios.toFormData = require('./helpers/toFormData');\n\n// Expose AxiosError class\naxios.AxiosError = require('../lib/core/AxiosError');\n\n// alias for CanceledError for backward compatibility\naxios.Cancel = axios.CanceledError;\n\n// Expose all/spread\naxios.all = function all(promises) {\n return Promise.all(promises);\n};\naxios.spread = require('./helpers/spread');\n\n// Expose isAxiosError\naxios.isAxiosError = require('./helpers/isAxiosError');\n\nmodule.exports = axios;\n\n// Allow use of default import syntax in TypeScript\nmodule.exports.default = axios;\n","module.exports = require('./lib/axios');","\nimport { setLogger } from '../ulity/debug';\nimport * as debug from '../ulity/debug';\nimport Event from '../ulity/event';\nimport Events from '../base/event';\nimport axios from 'axios';\nimport * as Base from '../base/export';\n\nexport default class RTCEndpoint extends Event\n{\n constructor(options)\n {\n super('RTCPusherPlayer');\n this.TAG = '[RTCPusherPlayer]';\n\n let defaults = {\n element: '',// html video element\n debug: false,// if output debug log\n zlmsdpUrl:'',\n simulcast:false,\n useCamera:true,\n audioEnable:true,\n videoEnable:true,\n recvOnly:false,\n resolution:{w:0,h:0},\n usedatachannel:false,\n };\n \n this.options = Object.assign({}, defaults, options);\n\n if(this.options.debug)\n {\n setLogger();\n }\n\n this.e = {\n onicecandidate:this._onIceCandidate.bind(this),\n ontrack:this._onTrack.bind(this),\n onicecandidateerror:this._onIceCandidateError.bind(this),\n onconnectionstatechange:this._onconnectionstatechange.bind(this),\n ondatachannelopen:this._onDataChannelOpen.bind(this),\n ondatachannelmsg:this._onDataChannelMsg.bind(this),\n ondatachannelerr:this._onDataChannelErr.bind(this),\n ondatachannelclose:this._onDataChannelClose.bind(this),\n };\n\n this._remoteStream = null;\n this._localStream = null;\n\n this._tracks = [];\n this.pc = new RTCPeerConnection(null);\n\n this.pc.onicecandidate = this.e.onicecandidate;\n this.pc.onicecandidateerror = this.e.onicecandidateerror;\n this.pc.ontrack = this.e.ontrack;\n this.pc.onconnectionstatechange = this.e.onconnectionstatechange;\n\n this.datachannel = null;\n if(this.options.usedatachannel){\n this.datachannel = this.pc.createDataChannel('chat');\n this.datachannel.onclose = this.e.ondatachannelclose;\n this.datachannel.onerror = this.e.ondatachannelerr;\n this.datachannel.onmessage = this.e.ondatachannelmsg;\n this.datachannel.onopen = this.e.ondatachannelopen;\n }\n\n if(!this.options.recvOnly && (this.options.audioEnable || this.options.videoEnable))\n this.start();\n else\n this.receive();\n \n }\n\n receive()\n {\n let audioTransceiver = null;\n let videoTransceiver = null;\n\n //debug.error(this.TAG,'this not implement');\n const AudioTransceiverInit = {\n direction: 'recvonly',\n sendEncodings:[]\n };\n const VideoTransceiverInit= {\n direction: 'recvonly',\n sendEncodings:[],\n };\n \n if(this.options.videoEnable){\n videoTransceiver = this.pc.addTransceiver('video',VideoTransceiverInit);\n }\n if(this.options.audioEnable){\n audioTransceiver = this.pc.addTransceiver('audio',AudioTransceiverInit);\n }\n \n this.pc.createOffer().then((desc)=>{\n debug.log(this.TAG,'offer:',desc.sdp);\n this.pc.setLocalDescription(desc).then(() => {\n axios({\n method: 'post',\n url:this.options.zlmsdpUrl,\n responseType:'json',\n data:desc.sdp,\n headers:{\n 'Content-Type':'text/plain;charset=utf-8'\n }\n }).then(response=>{\n let ret = response.data;//JSON.parse(response.data);\n if(ret.code != 0)\n {// mean failed for offer/anwser exchange \n this.dispatch(Events.WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED,ret);\n return;\n }\n let anwser = {};\n anwser.sdp = ret.sdp;\n anwser.type = 'answer';\n debug.log(this.TAG,'answer:',ret.sdp);\n\n this.pc.setRemoteDescription(anwser).then(()=>{\n debug.log(this.TAG,'set remote sucess');\n }).catch(e=>{\n debug.error(this.TAG,e);\n });\n });\n });\n }).catch(e=>{\n debug.error(this.TAG,e);\n });\n }\n\n start()\n {\n let videoConstraints = false;\n let audioConstraints = false;\n\n if(this.options.useCamera)\n {\n if(this.options.videoEnable)\n videoConstraints = new Base.VideoTrackConstraints(Base.VideoSourceInfo.CAMERA);\n if(this.options.audioEnable)\n audioConstraints = new Base.AudioTrackConstraints(Base.AudioSourceInfo.MIC);\n }\n else\n {\n if(this.options.videoEnable)\n {\n videoConstraints = new Base.VideoTrackConstraints(Base.VideoSourceInfo.SCREENCAST);\n if(this.options.audioEnable)\n audioConstraints = new Base.AudioTrackConstraints(Base.AudioSourceInfo.SCREENCAST);\n }\n else\n {\n if(this.options.audioEnable)\n audioConstraints = new Base.AudioTrackConstraints(Base.AudioSourceInfo.MIC);\n else\n {// error shared display media not only audio\n debug.error(this.TAG,'error paramter');\n }\n }\n \n }\n\n if(this.options.resolution.w !=0 && this.options.resolution.h!=0 && typeof videoConstraints == 'object'){\n videoConstraints.resolution = new Base.Resolution(this.options.resolution.w ,this.options.resolution.h);\n }\n\n Base.MediaStreamFactory.createMediaStream(new Base.StreamConstraints(\n audioConstraints, videoConstraints)).then(stream => {\n\n this._localStream = stream;\n\n this.dispatch(Events.WEBRTC_ON_LOCAL_STREAM,stream);\n\n const AudioTransceiverInit = {\n direction: 'sendrecv',\n sendEncodings:[]\n };\n const VideoTransceiverInit= {\n direction: 'sendrecv',\n sendEncodings:[],\n };\n \n if(this.options.simulcast && stream.getVideoTracks().length>0)\n {\n VideoTransceiverInit.sendEncodings = [\n { rid: 'h', active: true, maxBitrate: 1000000 },\n { rid: 'm', active: true, maxBitrate: 500000, scaleResolutionDownBy: 2 },\n { rid: 'l', active: true, maxBitrate: 200000, scaleResolutionDownBy: 4 }\n ];\n }\n let audioTransceiver = null;\n let videoTransceiver = null;\n if (this.options.audioEnable) {\n if (stream.getAudioTracks().length > 0) {\n audioTransceiver = this.pc.addTransceiver(stream.getAudioTracks()[0],\n AudioTransceiverInit);\n }\n else {\n AudioTransceiverInit.direction = 'recvonly';\n audioTransceiver = this.pc.addTransceiver('audio', AudioTransceiverInit);\n }\n }\n \n if (this.options.videoEnable) {\n if (stream.getVideoTracks().length > 0) {\n videoTransceiver = this.pc.addTransceiver(stream.getVideoTracks()[0],\n VideoTransceiverInit);\n }\n else {\n VideoTransceiverInit.direction = 'recvonly';\n videoTransceiver = this.pc.addTransceiver('video',\n VideoTransceiverInit);\n }\n }\n\n /*\n stream.getTracks().forEach((track,idx)=>{\n debug.log(this.TAG,track);\n this.pc.addTrack(track);\n });\n */\n this.pc.createOffer().then((desc)=>{\n debug.log(this.TAG,'offer:',desc.sdp);\n this.pc.setLocalDescription(desc).then(() => {\n axios({\n method: 'post',\n url:this.options.zlmsdpUrl,\n responseType:'json',\n data:desc.sdp,\n headers:{\n 'Content-Type':'text/plain;charset=utf-8'\n }\n }).then(response=>{\n let ret = response.data;//JSON.parse(response.data);\n if(ret.code != 0)\n {// mean failed for offer/anwser exchange \n this.dispatch(Events.WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED,ret);\n return;\n }\n let anwser = {};\n anwser.sdp = ret.sdp;\n anwser.type = 'answer';\n debug.log(this.TAG,'answer:',ret.sdp);\n \n this.pc.setRemoteDescription(anwser).then(()=>{\n debug.log(this.TAG,'set remote sucess');\n }).catch(e=>{\n debug.error(this.TAG,e);\n });\n });\n });\n }).catch(e=>{\n debug.error(this.TAG,e);\n });\n\n }).catch(e=>{\n this.dispatch(Events.CAPTURE_STREAM_FAILED);\n //debug.error(this.TAG,e);\n });\n \n //const offerOptions = {};\n /*\n if (typeof this.pc.addTransceiver === 'function') {\n // |direction| seems not working on Safari.\n this.pc.addTransceiver('audio', { direction: 'recvonly' });\n this.pc.addTransceiver('video', { direction: 'recvonly' });\n } else {\n offerOptions.offerToReceiveAudio = true;\n offerOptions.offerToReceiveVideo = true;\n }\n */\n\n\n\n }\n _onIceCandidate(event) {\n if (event.candidate) { \n debug.log(this.TAG,'Remote ICE candidate: \\n ' + event.candidate.candidate);\n // Send the candidate to the remote peer\n }\n else {\n // All ICE candidates have been sent\n }\n }\n\n _onTrack(event){\n this._tracks.push(event.track);\n if(this.options.element && event.streams && event.streams.length>0)\n {\n this.options.element.srcObject = event.streams[0];\n this._remoteStream = event.streams[0];\n\n this.dispatch(Events.WEBRTC_ON_REMOTE_STREAMS,event);\n }\n else\n {\n if(this.pc.getReceivers().length ==this._tracks.length){\n debug.log(this.TAG,'play remote stream ');\n this._remoteStream = new MediaStream(this._tracks);\n this.options.element.srcObject = this._remoteStream;\n }else{\n debug.error(this.TAG,'wait stream track finish');\n }\n }\n }\n\n _onIceCandidateError(event){\n this.dispatch(Events.WEBRTC_ICE_CANDIDATE_ERROR,event);\n }\n\n _onconnectionstatechange(event) {\n this.dispatch(Events.WEBRTC_ON_CONNECTION_STATE_CHANGE, this.pc.connectionState);\n }\n\n _onDataChannelOpen(event) {\n debug.log(this.TAG,'ondatachannel open:',event);\n this.dispatch(Events.WEBRTC_ON_DATA_CHANNEL_OPEN,event);\n }\n _onDataChannelMsg(event) {\n debug.log(this.TAG,'ondatachannel msg:',event);\n this.dispatch(Events.WEBRTC_ON_DATA_CHANNEL_MSG,event);\n }\n _onDataChannelErr(event){\n debug.log(this.TAG,'ondatachannel err:',event);\n this.dispatch(Events.WEBRTC_ON_DATA_CHANNEL_ERR,event);\n }\n _onDataChannelClose(event){\n debug.log(this.TAG,'ondatachannel close:',event);\n this.dispatch(Events.WEBRTC_ON_DATA_CHANNEL_CLOSE,event);\n }\n sendMsg(data){\n if(this.datachannel !=null){\n this.datachannel.send(data);\n }else{\n debug.error(this.TAG,'data channel is null');\n }\n }\n closeDataChannel(){\n if(this.datachannel){\n this.datachannel.close();\n this.datachannel = null;\n }\n }\n close()\n { \n this.closeDataChannel();\n if(this.pc)\n {\n this.pc.close();\n this.pc=null;\n }\n\n if(this.options)\n {\n this.options=null;\n }\n\n if(this._localStream)\n {\n this._localStream.getTracks().forEach((track,idx)=>{\n track.stop();\n });\n }\n\n if(this._remoteStream)\n {\n this._remoteStream.getTracks().forEach((track,idx)=>{\n track.stop();\n });\n }\n\n this._tracks.forEach((track, idx) => {\n track.stop();\n });\n this._tracks = [];\n }\n\n get remoteStream()\n {\n return this._remoteStream;\n }\n \n get localStream()\n {\n return this._localStream;\n }\n}\n","import * as mediaformat from './mediaformat';\nimport * as MediaFactory from './mediastream-factory';\n\n\nconst quickScan=[\n {\n 'label': '4K(UHD)',\n 'width': 3840,\n 'height': 2160\n },\n {\n 'label': '1080p(FHD)',\n 'width': 1920,\n 'height': 1080\n },\n {\n 'label': 'UXGA',\n 'width': 1600,\n 'height': 1200,\n 'ratio': '4:3'\n },\n {\n 'label': '720p(HD)',\n 'width': 1280,\n 'height': 720\n },\n {\n 'label': 'SVGA',\n 'width': 800,\n 'height': 600\n },\n {\n 'label': 'VGA',\n 'width': 640,\n 'height': 480\n },\n {\n 'label': '360p(nHD)',\n 'width': 640,\n 'height': 360\n },\n {\n 'label': 'CIF',\n 'width': 352,\n 'height': 288\n },\n {\n 'label': 'QVGA',\n 'width': 320,\n 'height': 240\n },\n {\n 'label': 'QCIF',\n 'width': 176,\n 'height': 144\n },\n {\n 'label': 'QQVGA',\n 'width': 160,\n 'height': 120\n }\n];\n\n\n\n\nexport default function GetSupportCameraResolutions(){\n return new Promise(function (resolve, reject) {\n let resolutions = [];\n let ok = 0;\n let err = 0;\n for (let i = 0; i < quickScan.length; ++i) {\n let videoConstraints = new MediaFactory.VideoTrackConstraints(mediaformat.VideoSourceInfo.CAMERA);\n videoConstraints.resolution = new mediaformat.Resolution(quickScan[i].width, quickScan[i].height);\n\n MediaFactory.MediaStreamFactory.createMediaStream(new MediaFactory.StreamConstraints(\n false, videoConstraints)).then(stream => {\n resolutions.push(quickScan[i]);\n ok++;\n if(ok+err == quickScan.length)\n {\n resolve(resolutions);\n }\n }).catch(e => {\n err++;\n if(ok+err == quickScan.length)\n {\n resolve(resolutions);\n }\n });\n }\n });\n}\n\nexport function GetAllScanResolution()\n{\n return quickScan;\n}\nexport function isSupportResolution(w,h)\n{\n return new Promise(function (resolve, reject) {\n let videoConstraints = new MediaFactory.VideoTrackConstraints(mediaformat.VideoSourceInfo.CAMERA);\n videoConstraints.resolution = new mediaformat.Resolution(w,h);\n\n MediaFactory.MediaStreamFactory.createMediaStream(new MediaFactory.StreamConstraints(\n false, videoConstraints)).then(stream => {\n resolve();\n }).catch(e => {\n reject(e);\n });\n });\n}","import * as events from './base/event';\nimport * as compile from './ulity/version';\nimport * as media from './base/export';\nimport * as endpoint from './endpoint/endpoint';\nimport * as resolution from './base/resolutionfind';\n\n\n\nconsole.log('build date:',compile.BUILD_DATE);\nconsole.log('version:',compile.VERSION);\n\nexport const Events = events.default;\nexport const Media = media;\nexport const Endpoint = endpoint.default;\nexport const GetSupportCameraResolutions = resolution.default;\nexport const GetAllScanResolution = resolution.GetAllScanResolution;\nexport const isSupportResolution = resolution.isSupportResolution;"],"names":["Events","WEBRTC_NOT_SUPPORT","WEBRTC_ICE_CANDIDATE_ERROR","WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED","WEBRTC_ON_REMOTE_STREAMS","WEBRTC_ON_LOCAL_STREAM","WEBRTC_ON_CONNECTION_STATE_CHANGE","WEBRTC_ON_DATA_CHANNEL_OPEN","WEBRTC_ON_DATA_CHANNEL_CLOSE","WEBRTC_ON_DATA_CHANNEL_ERR","WEBRTC_ON_DATA_CHANNEL_MSG","CAPTURE_STREAM_FAILED","VERSION","BUILD_DATE","isFirefox","window","navigator","userAgent","match","isChrome","isEdge","AudioSourceInfo","MIC","SCREENCAST","FILE","MIXED","VideoSourceInfo","CAMERA","TrackKind","AUDIO","VIDEO","AUDIO_AND_VIDEO","Resolution","constructor","width","height","log","isObject","utils.log","shimGetUserMedia","shimGetDisplayMedia","shimOnTrack","utils.wrapPeerConnectionEvent","utils.filterStats","shimPeerConnection","filterIceServers","utils.deprecated","sdp","SDPUtils","shimRTCPeerConnection","utils.compactObject","utils.detectBrowser","utils.extractVersion","utils.disableLog","utils.disableWarnings","chromeShim.shimPeerConnection","commonShim.shimAddIceCandidateNullOrEmpty","chromeShim.shimGetUserMedia","chromeShim.shimMediaStream","chromeShim.shimOnTrack","chromeShim.shimAddTrackRemoveTrack","chromeShim.shimGetSendersWithDtmf","chromeShim.shimGetStats","chromeShim.shimSenderReceiverGetStats","chromeShim.fixNegotiationNeeded","commonShim.shimRTCIceCandidate","commonShim.shimConnectionState","commonShim.shimMaxMessageSize","commonShim.shimSendThrowTypeError","commonShim.removeExtmapAllowMixed","firefoxShim.shimPeerConnection","firefoxShim.shimGetUserMedia","firefoxShim.shimOnTrack","firefoxShim.shimRemoveStream","firefoxShim.shimSenderGetStats","firefoxShim.shimReceiverGetStats","firefoxShim.shimRTCDataChannel","firefoxShim.shimAddTransceiver","firefoxShim.shimGetParameters","firefoxShim.shimCreateOffer","firefoxShim.shimCreateAnswer","edgeShim.shimPeerConnection","edgeShim.shimGetUserMedia","edgeShim.shimGetDisplayMedia","edgeShim.shimReplaceTrack","safariShim.shimRTCIceServerUrls","safariShim.shimCreateOfferLegacy","safariShim.shimCallbacksAPI","safariShim.shimLocalStreamsAPI","safariShim.shimRemoteStreamsAPI","safariShim.shimTrackEventTransceiver","safariShim.shimGetUserMedia","safariShim.shimAudioContext","AudioTrackConstraints","source","Object","values","MediaFormatModule","some","v","TypeError","deviceId","undefined","VideoTrackConstraints","resolution","frameRate","StreamConstraints","audioConstraints","videoConstraints","audio","video","isVideoConstrainsForScreenCast","constraints","MediaStreamFactory","createMediaStream","Promise","reject","utils","mediaConstraints","create","exact","mediaSource","mediaDevices","getDisplayMedia","getUserMedia","logger","errorLogger","setLogger","console","error","message","optionalParams","Event","type","listener","on","event","fn","push","off","index","indexOf","splice","offAll","dispatch","data","map","each","apply","AxiosError","transitional","transitionalDefaults","CanceledError","require$$0","require$$1","toFormData","require$$2","defaults","validators","InterceptorManager","Axios","axios","require$$3","require$$4","require$$5","require$$6","require$$7","RTCEndpoint","options","TAG","element","debug","zlmsdpUrl","simulcast","useCamera","audioEnable","videoEnable","recvOnly","w","h","usedatachannel","assign","e","onicecandidate","_onIceCandidate","bind","ontrack","_onTrack","onicecandidateerror","_onIceCandidateError","onconnectionstatechange","_onconnectionstatechange","ondatachannelopen","_onDataChannelOpen","ondatachannelmsg","_onDataChannelMsg","ondatachannelerr","_onDataChannelErr","ondatachannelclose","_onDataChannelClose","_remoteStream","_localStream","_tracks","pc","RTCPeerConnection","datachannel","createDataChannel","onclose","onerror","onmessage","onopen","start","receive","AudioTransceiverInit","direction","sendEncodings","VideoTransceiverInit","addTransceiver","createOffer","then","desc","setLocalDescription","method","url","responseType","headers","response","ret","code","anwser","setRemoteDescription","catch","Base","stream","getVideoTracks","length","rid","active","maxBitrate","scaleResolutionDownBy","getAudioTracks","audioTransceiver","videoTransceiver","candidate","track","streams","srcObject","getReceivers","MediaStream","connectionState","sendMsg","send","closeDataChannel","close","getTracks","forEach","idx","stop","remoteStream","localStream","quickScan","GetSupportCameraResolutions","resolve","resolutions","ok","err","i","MediaFactory","mediaformat","GetAllScanResolution","isSupportResolution","compile","events","Media","media","Endpoint","endpoint"],"mappings":"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"} | |
| 3 | 3 | \ No newline at end of file | ... | ... |