@sbhjt-gr/react-native-webrtc 124.0.3 → 124.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (361) hide show
  1. package/.clang-format +11 -11
  2. package/.eslintignore +6 -6
  3. package/.nvmrc +1 -1
  4. package/ISSUE_TEMPLATE.md +40 -40
  5. package/LICENSE +22 -22
  6. package/README.md +103 -103
  7. package/android/build.gradle +37 -37
  8. package/android/consumer-rules.pro +3 -3
  9. package/android/src/main/AndroidManifest.xml +11 -11
  10. package/android/src/main/java/com/oney/WebRTCModule/AbstractVideoCaptureController.java +113 -113
  11. package/android/src/main/java/com/oney/WebRTCModule/CameraCaptureController.java +338 -338
  12. package/android/src/main/java/com/oney/WebRTCModule/CameraEventsHandler.java +49 -49
  13. package/android/src/main/java/com/oney/WebRTCModule/DataChannelWrapper.java +99 -99
  14. package/android/src/main/java/com/oney/WebRTCModule/DataPacketCryptorManager.java +62 -62
  15. package/android/src/main/java/com/oney/WebRTCModule/DisplayUtils.java +16 -16
  16. package/android/src/main/java/com/oney/WebRTCModule/EglUtils.java +66 -66
  17. package/android/src/main/java/com/oney/WebRTCModule/GetUserMediaImpl.java +539 -539
  18. package/android/src/main/java/com/oney/WebRTCModule/LibraryLoader.java +21 -21
  19. package/android/src/main/java/com/oney/WebRTCModule/MediaProjectionNotification.java +70 -70
  20. package/android/src/main/java/com/oney/WebRTCModule/MediaProjectionService.java +82 -82
  21. package/android/src/main/java/com/oney/WebRTCModule/PeerConnectionObserver.java +588 -588
  22. package/android/src/main/java/com/oney/WebRTCModule/RTCCryptoManager.java +493 -493
  23. package/android/src/main/java/com/oney/WebRTCModule/RTCVideoViewManager.java +98 -98
  24. package/android/src/main/java/com/oney/WebRTCModule/ReactBridgeUtil.java +35 -35
  25. package/android/src/main/java/com/oney/WebRTCModule/ScreenCaptureController.java +94 -94
  26. package/android/src/main/java/com/oney/WebRTCModule/SerializeUtils.java +342 -342
  27. package/android/src/main/java/com/oney/WebRTCModule/StringUtils.java +100 -100
  28. package/android/src/main/java/com/oney/WebRTCModule/ThreadUtils.java +41 -41
  29. package/android/src/main/java/com/oney/WebRTCModule/TrackCapturerEventsEmitter.java +34 -34
  30. package/android/src/main/java/com/oney/WebRTCModule/VideoTrackAdapter.java +137 -137
  31. package/android/src/main/java/com/oney/WebRTCModule/WebRTCModule.java +1649 -1643
  32. package/android/src/main/java/com/oney/WebRTCModule/WebRTCModuleOptions.java +33 -33
  33. package/android/src/main/java/com/oney/WebRTCModule/WebRTCModulePackage.java +21 -21
  34. package/android/src/main/java/com/oney/WebRTCModule/WebRTCView.java +583 -583
  35. package/android/src/main/java/com/oney/WebRTCModule/palabra/PalabraClient.java +529 -501
  36. package/android/src/main/java/com/oney/WebRTCModule/palabra/PalabraConfig.java +17 -17
  37. package/android/src/main/java/com/oney/WebRTCModule/palabra/PalabraListener.java +7 -7
  38. package/android/src/main/java/com/oney/WebRTCModule/videoEffects/ProcessorProvider.java +38 -38
  39. package/android/src/main/java/com/oney/WebRTCModule/videoEffects/VideoEffectProcessor.java +59 -59
  40. package/android/src/main/java/com/oney/WebRTCModule/videoEffects/VideoFrameProcessor.java +19 -19
  41. package/android/src/main/java/com/oney/WebRTCModule/videoEffects/VideoFrameProcessorFactoryInterface.java +12 -12
  42. package/android/src/main/java/com/oney/WebRTCModule/webrtcutils/H264AndSoftwareVideoDecoderFactory.java +73 -73
  43. package/android/src/main/java/com/oney/WebRTCModule/webrtcutils/H264AndSoftwareVideoEncoderFactory.java +73 -73
  44. package/android/src/main/java/com/oney/WebRTCModule/webrtcutils/SoftwareVideoDecoderFactoryProxy.java +36 -36
  45. package/android/src/main/java/com/oney/WebRTCModule/webrtcutils/SoftwareVideoEncoderFactoryProxy.java +36 -36
  46. package/android/src/main/java/org/webrtc/Camera1Helper.java +54 -54
  47. package/android/src/main/java/org/webrtc/Camera2Helper.java +52 -52
  48. package/android/src/main/res/values/strings.xml +5 -5
  49. package/android/src/main/res/values/styles.xml +8 -8
  50. package/ios/RCTWebRTC/CaptureController.h +18 -18
  51. package/ios/RCTWebRTC/CaptureController.m +28 -28
  52. package/ios/RCTWebRTC/CapturerEventsDelegate.h +12 -12
  53. package/ios/RCTWebRTC/DataChannelWrapper.h +27 -27
  54. package/ios/RCTWebRTC/DataChannelWrapper.m +42 -42
  55. package/ios/RCTWebRTC/I420Converter.h +22 -22
  56. package/ios/RCTWebRTC/I420Converter.m +164 -164
  57. package/ios/RCTWebRTC/PIPController.h +24 -24
  58. package/ios/RCTWebRTC/PIPController.m +234 -234
  59. package/ios/RCTWebRTC/PalabraAudioSink.h +13 -13
  60. package/ios/RCTWebRTC/PalabraAudioSink.m +18 -18
  61. package/ios/RCTWebRTC/PalabraClient.h +42 -36
  62. package/ios/RCTWebRTC/PalabraClient.m +680 -644
  63. package/ios/RCTWebRTC/RCTConvert+WebRTC.h +16 -16
  64. package/ios/RCTWebRTC/RCTConvert+WebRTC.m +206 -206
  65. package/ios/RCTWebRTC/RTCMediaStreamTrack+React.h +10 -10
  66. package/ios/RCTWebRTC/RTCMediaStreamTrack+React.m +16 -16
  67. package/ios/RCTWebRTC/RTCVideoViewManager.h +29 -29
  68. package/ios/RCTWebRTC/RTCVideoViewManager.m +411 -411
  69. package/ios/RCTWebRTC/SampleBufferVideoCallView.h +12 -12
  70. package/ios/RCTWebRTC/SampleBufferVideoCallView.m +178 -178
  71. package/ios/RCTWebRTC/ScreenCaptureController.h +20 -20
  72. package/ios/RCTWebRTC/ScreenCaptureController.m +82 -82
  73. package/ios/RCTWebRTC/ScreenCapturePickerViewManager.h +7 -7
  74. package/ios/RCTWebRTC/ScreenCapturePickerViewManager.m +59 -59
  75. package/ios/RCTWebRTC/ScreenCapturer.h +19 -19
  76. package/ios/RCTWebRTC/ScreenCapturer.m +263 -263
  77. package/ios/RCTWebRTC/SerializeUtils.h +28 -28
  78. package/ios/RCTWebRTC/SerializeUtils.m +314 -314
  79. package/ios/RCTWebRTC/SocketConnection.h +13 -13
  80. package/ios/RCTWebRTC/SocketConnection.m +137 -137
  81. package/ios/RCTWebRTC/TrackCapturerEventsEmitter.h +14 -14
  82. package/ios/RCTWebRTC/TrackCapturerEventsEmitter.m +36 -36
  83. package/ios/RCTWebRTC/VideoCaptureController.h +21 -21
  84. package/ios/RCTWebRTC/VideoCaptureController.m +328 -328
  85. package/ios/RCTWebRTC/WLVAudioDevice.h +12 -12
  86. package/ios/RCTWebRTC/WLVAudioDevice.m +137 -137
  87. package/ios/RCTWebRTC/WebRTCModule+Palabra.h +4 -4
  88. package/ios/RCTWebRTC/WebRTCModule+Palabra.m +92 -83
  89. package/ios/RCTWebRTC/WebRTCModule+Permissions.m +75 -75
  90. package/ios/RCTWebRTC/WebRTCModule+RTCAudioSession.m +20 -20
  91. package/ios/RCTWebRTC/WebRTCModule+RTCDataChannel.h +14 -14
  92. package/ios/RCTWebRTC/WebRTCModule+RTCDataChannel.m +165 -165
  93. package/ios/RCTWebRTC/WebRTCModule+RTCFrameCryptor.m +611 -611
  94. package/ios/RCTWebRTC/WebRTCModule+RTCMediaStream.h +13 -13
  95. package/ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m +728 -728
  96. package/ios/RCTWebRTC/WebRTCModule+RTCPeerConnection.h +24 -24
  97. package/ios/RCTWebRTC/WebRTCModule+RTCPeerConnection.m +1004 -1004
  98. package/ios/RCTWebRTC/WebRTCModule+Transceivers.m +267 -267
  99. package/ios/RCTWebRTC/WebRTCModule+VideoTrackAdapter.h +12 -12
  100. package/ios/RCTWebRTC/WebRTCModule+VideoTrackAdapter.m +166 -166
  101. package/ios/RCTWebRTC/WebRTCModule.h +58 -58
  102. package/ios/RCTWebRTC/WebRTCModule.m +169 -169
  103. package/ios/RCTWebRTC/WebRTCModuleOptions.h +24 -24
  104. package/ios/RCTWebRTC/WebRTCModuleOptions.m +31 -31
  105. package/ios/RCTWebRTC/videoEffects/ProcessorProvider.h +9 -9
  106. package/ios/RCTWebRTC/videoEffects/ProcessorProvider.m +23 -23
  107. package/ios/RCTWebRTC/videoEffects/VideoEffectProcessor.h +13 -13
  108. package/ios/RCTWebRTC/videoEffects/VideoEffectProcessor.m +23 -23
  109. package/ios/RCTWebRTC/videoEffects/VideoFrameProcessor.h +8 -8
  110. package/ios/RCTWebRTC.xcodeproj/project.pbxproj +404 -404
  111. package/ios/RCTWebRTC.xcworkspace/contents.xcworkspacedata +10 -10
  112. package/lib/commonjs/Constraints.js.map +1 -1
  113. package/lib/commonjs/EventEmitter.js.map +1 -1
  114. package/lib/commonjs/Logger.js.map +1 -1
  115. package/lib/commonjs/MediaDevices.js +17 -17
  116. package/lib/commonjs/MediaDevices.js.map +1 -1
  117. package/lib/commonjs/MediaStream.js +19 -19
  118. package/lib/commonjs/MediaStream.js.map +1 -1
  119. package/lib/commonjs/MediaStreamError.js.map +1 -1
  120. package/lib/commonjs/MediaStreamErrorEvent.js.map +1 -1
  121. package/lib/commonjs/MediaStreamTrack.js +28 -28
  122. package/lib/commonjs/MediaStreamTrack.js.map +1 -1
  123. package/lib/commonjs/MediaStreamTrackEvent.js +6 -6
  124. package/lib/commonjs/MediaStreamTrackEvent.js.map +1 -1
  125. package/lib/commonjs/MessageEvent.js +7 -7
  126. package/lib/commonjs/MessageEvent.js.map +1 -1
  127. package/lib/commonjs/Permissions.js +28 -28
  128. package/lib/commonjs/Permissions.js.map +1 -1
  129. package/lib/commonjs/RTCAudioSession.js +4 -4
  130. package/lib/commonjs/RTCAudioSession.js.map +1 -1
  131. package/lib/commonjs/RTCDataChannel.js +2 -2
  132. package/lib/commonjs/RTCDataChannel.js.map +1 -1
  133. package/lib/commonjs/RTCDataChannelEvent.js +6 -6
  134. package/lib/commonjs/RTCDataChannelEvent.js.map +1 -1
  135. package/lib/commonjs/RTCDataPacketCryptor.js.map +1 -1
  136. package/lib/commonjs/RTCDataPacketCryptorFactory.js.map +1 -1
  137. package/lib/commonjs/RTCErrorEvent.js +3 -3
  138. package/lib/commonjs/RTCErrorEvent.js.map +1 -1
  139. package/lib/commonjs/RTCFrameCryptor.js +8 -8
  140. package/lib/commonjs/RTCFrameCryptor.js.map +1 -1
  141. package/lib/commonjs/RTCFrameCryptorFactory.js.map +1 -1
  142. package/lib/commonjs/RTCIceCandidate.js.map +1 -1
  143. package/lib/commonjs/RTCIceCandidateEvent.js +7 -7
  144. package/lib/commonjs/RTCIceCandidateEvent.js.map +1 -1
  145. package/lib/commonjs/RTCKeyProvider.js.map +1 -1
  146. package/lib/commonjs/RTCPIPView.js +2 -2
  147. package/lib/commonjs/RTCPIPView.js.map +1 -1
  148. package/lib/commonjs/RTCPIPView.web.js.map +1 -1
  149. package/lib/commonjs/RTCPeerConnection.js +36 -36
  150. package/lib/commonjs/RTCPeerConnection.js.map +1 -1
  151. package/lib/commonjs/RTCRtcpParameters.js.map +1 -1
  152. package/lib/commonjs/RTCRtpCapabilities.js +2 -2
  153. package/lib/commonjs/RTCRtpCapabilities.js.map +1 -1
  154. package/lib/commonjs/RTCRtpCodecCapability.js.map +1 -1
  155. package/lib/commonjs/RTCRtpCodecParameters.js.map +1 -1
  156. package/lib/commonjs/RTCRtpEncodingParameters.js.map +1 -1
  157. package/lib/commonjs/RTCRtpHeaderExtension.js.map +1 -1
  158. package/lib/commonjs/RTCRtpParameters.js.map +1 -1
  159. package/lib/commonjs/RTCRtpReceiveParameters.js.map +1 -1
  160. package/lib/commonjs/RTCRtpReceiver.js +7 -7
  161. package/lib/commonjs/RTCRtpReceiver.js.map +1 -1
  162. package/lib/commonjs/RTCRtpSendParameters.js +3 -3
  163. package/lib/commonjs/RTCRtpSendParameters.js.map +1 -1
  164. package/lib/commonjs/RTCRtpSender.js +7 -7
  165. package/lib/commonjs/RTCRtpSender.js.map +1 -1
  166. package/lib/commonjs/RTCRtpTransceiver.js.map +1 -1
  167. package/lib/commonjs/RTCSessionDescription.js.map +1 -1
  168. package/lib/commonjs/RTCTrackEvent.js +6 -6
  169. package/lib/commonjs/RTCTrackEvent.js.map +1 -1
  170. package/lib/commonjs/RTCUtil.js +28 -28
  171. package/lib/commonjs/RTCUtil.js.map +1 -1
  172. package/lib/commonjs/RTCView.js +5 -5
  173. package/lib/commonjs/RTCView.js.map +1 -1
  174. package/lib/commonjs/RTCView.web.js.map +1 -1
  175. package/lib/commonjs/ScreenCapturePickerView.js.map +1 -1
  176. package/lib/commonjs/ScreenCapturePickerView.web.js.map +1 -1
  177. package/lib/commonjs/getDisplayMedia.js.map +1 -1
  178. package/lib/commonjs/getUserMedia.js.map +1 -1
  179. package/lib/commonjs/index.js.map +1 -1
  180. package/lib/commonjs/index.web.js.map +1 -1
  181. package/lib/commonjs/webStream.js.map +1 -1
  182. package/lib/module/Constraints.js.map +1 -1
  183. package/lib/module/EventEmitter.js.map +1 -1
  184. package/lib/module/Logger.js.map +1 -1
  185. package/lib/module/MediaDevices.js +17 -17
  186. package/lib/module/MediaDevices.js.map +1 -1
  187. package/lib/module/MediaStream.js +19 -19
  188. package/lib/module/MediaStream.js.map +1 -1
  189. package/lib/module/MediaStreamError.js.map +1 -1
  190. package/lib/module/MediaStreamErrorEvent.js.map +1 -1
  191. package/lib/module/MediaStreamTrack.js +28 -28
  192. package/lib/module/MediaStreamTrack.js.map +1 -1
  193. package/lib/module/MediaStreamTrackEvent.js +6 -6
  194. package/lib/module/MediaStreamTrackEvent.js.map +1 -1
  195. package/lib/module/MessageEvent.js +7 -7
  196. package/lib/module/MessageEvent.js.map +1 -1
  197. package/lib/module/Permissions.js +28 -28
  198. package/lib/module/Permissions.js.map +1 -1
  199. package/lib/module/RTCAudioSession.js +4 -4
  200. package/lib/module/RTCAudioSession.js.map +1 -1
  201. package/lib/module/RTCDataChannel.js +2 -2
  202. package/lib/module/RTCDataChannel.js.map +1 -1
  203. package/lib/module/RTCDataChannelEvent.js +6 -6
  204. package/lib/module/RTCDataChannelEvent.js.map +1 -1
  205. package/lib/module/RTCDataPacketCryptor.js.map +1 -1
  206. package/lib/module/RTCDataPacketCryptorFactory.js.map +1 -1
  207. package/lib/module/RTCErrorEvent.js +3 -3
  208. package/lib/module/RTCErrorEvent.js.map +1 -1
  209. package/lib/module/RTCFrameCryptor.js +8 -8
  210. package/lib/module/RTCFrameCryptor.js.map +1 -1
  211. package/lib/module/RTCFrameCryptorFactory.js.map +1 -1
  212. package/lib/module/RTCIceCandidate.js.map +1 -1
  213. package/lib/module/RTCIceCandidateEvent.js +7 -7
  214. package/lib/module/RTCIceCandidateEvent.js.map +1 -1
  215. package/lib/module/RTCKeyProvider.js.map +1 -1
  216. package/lib/module/RTCPIPView.js +2 -2
  217. package/lib/module/RTCPIPView.js.map +1 -1
  218. package/lib/module/RTCPIPView.web.js.map +1 -1
  219. package/lib/module/RTCPeerConnection.js +36 -36
  220. package/lib/module/RTCPeerConnection.js.map +1 -1
  221. package/lib/module/RTCRtcpParameters.js.map +1 -1
  222. package/lib/module/RTCRtpCapabilities.js +2 -2
  223. package/lib/module/RTCRtpCapabilities.js.map +1 -1
  224. package/lib/module/RTCRtpCodecCapability.js.map +1 -1
  225. package/lib/module/RTCRtpCodecParameters.js.map +1 -1
  226. package/lib/module/RTCRtpEncodingParameters.js.map +1 -1
  227. package/lib/module/RTCRtpHeaderExtension.js.map +1 -1
  228. package/lib/module/RTCRtpParameters.js.map +1 -1
  229. package/lib/module/RTCRtpReceiveParameters.js.map +1 -1
  230. package/lib/module/RTCRtpReceiver.js +7 -7
  231. package/lib/module/RTCRtpReceiver.js.map +1 -1
  232. package/lib/module/RTCRtpSendParameters.js +3 -3
  233. package/lib/module/RTCRtpSendParameters.js.map +1 -1
  234. package/lib/module/RTCRtpSender.js +7 -7
  235. package/lib/module/RTCRtpSender.js.map +1 -1
  236. package/lib/module/RTCRtpTransceiver.js.map +1 -1
  237. package/lib/module/RTCSessionDescription.js.map +1 -1
  238. package/lib/module/RTCTrackEvent.js +6 -6
  239. package/lib/module/RTCTrackEvent.js.map +1 -1
  240. package/lib/module/RTCUtil.js +28 -28
  241. package/lib/module/RTCUtil.js.map +1 -1
  242. package/lib/module/RTCView.js +5 -5
  243. package/lib/module/RTCView.js.map +1 -1
  244. package/lib/module/RTCView.web.js.map +1 -1
  245. package/lib/module/ScreenCapturePickerView.js.map +1 -1
  246. package/lib/module/ScreenCapturePickerView.web.js.map +1 -1
  247. package/lib/module/getDisplayMedia.js.map +1 -1
  248. package/lib/module/getUserMedia.js.map +1 -1
  249. package/lib/module/index.js.map +1 -1
  250. package/lib/module/index.web.js.map +1 -1
  251. package/lib/module/webStream.js.map +1 -1
  252. package/lib/typescript/Constraints.d.ts +19 -19
  253. package/lib/typescript/EventEmitter.d.ts +6 -6
  254. package/lib/typescript/Logger.d.ts +13 -13
  255. package/lib/typescript/MediaDevices.d.ts +30 -30
  256. package/lib/typescript/MediaStream.d.ts +48 -48
  257. package/lib/typescript/MediaStreamError.d.ts +6 -6
  258. package/lib/typescript/MediaStreamErrorEvent.d.ts +6 -6
  259. package/lib/typescript/MediaStreamTrack.d.ts +101 -101
  260. package/lib/typescript/MediaStreamTrackEvent.d.ts +19 -19
  261. package/lib/typescript/MessageEvent.d.ts +20 -20
  262. package/lib/typescript/Permissions.d.ts +55 -55
  263. package/lib/typescript/RTCAudioSession.d.ts +10 -10
  264. package/lib/typescript/RTCDataChannel.d.ts +43 -43
  265. package/lib/typescript/RTCDataChannelEvent.d.ts +19 -19
  266. package/lib/typescript/RTCDataPacketCryptor.d.ts +12 -12
  267. package/lib/typescript/RTCDataPacketCryptorFactory.d.ts +6 -6
  268. package/lib/typescript/RTCErrorEvent.d.ts +12 -12
  269. package/lib/typescript/RTCFrameCryptor.d.ts +47 -47
  270. package/lib/typescript/RTCFrameCryptorFactory.d.ts +21 -21
  271. package/lib/typescript/RTCIceCandidate.d.ts +17 -17
  272. package/lib/typescript/RTCIceCandidateEvent.d.ts +20 -20
  273. package/lib/typescript/RTCKeyProvider.d.ts +21 -21
  274. package/lib/typescript/RTCPIPView.d.ts +15 -15
  275. package/lib/typescript/RTCPIPView.web.d.ts +13 -13
  276. package/lib/typescript/RTCPeerConnection.d.ts +117 -117
  277. package/lib/typescript/RTCRtcpParameters.d.ts +10 -10
  278. package/lib/typescript/RTCRtpCapabilities.d.ts +9 -9
  279. package/lib/typescript/RTCRtpCodecCapability.d.ts +7 -7
  280. package/lib/typescript/RTCRtpCodecParameters.d.ts +16 -16
  281. package/lib/typescript/RTCRtpEncodingParameters.d.ts +23 -23
  282. package/lib/typescript/RTCRtpHeaderExtension.d.ts +12 -12
  283. package/lib/typescript/RTCRtpParameters.d.ts +19 -19
  284. package/lib/typescript/RTCRtpReceiveParameters.d.ts +4 -4
  285. package/lib/typescript/RTCRtpReceiver.d.ts +21 -21
  286. package/lib/typescript/RTCRtpSendParameters.d.ts +20 -20
  287. package/lib/typescript/RTCRtpSender.d.ts +22 -22
  288. package/lib/typescript/RTCRtpTransceiver.d.ts +31 -31
  289. package/lib/typescript/RTCSessionDescription.d.ts +12 -12
  290. package/lib/typescript/RTCTrackEvent.d.ts +29 -29
  291. package/lib/typescript/RTCUtil.d.ts +37 -37
  292. package/lib/typescript/RTCView.d.ts +117 -117
  293. package/lib/typescript/RTCView.web.d.ts +25 -25
  294. package/lib/typescript/ScreenCapturePickerView.d.ts +2 -2
  295. package/lib/typescript/ScreenCapturePickerView.web.d.ts +1 -1
  296. package/lib/typescript/getDisplayMedia.d.ts +2 -2
  297. package/lib/typescript/getUserMedia.d.ts +7 -7
  298. package/lib/typescript/index.d.ts +22 -22
  299. package/lib/typescript/index.web.d.ts +101 -101
  300. package/lib/typescript/webStream.d.ts +3 -3
  301. package/livekit-react-native-webrtc.podspec +29 -29
  302. package/macos/RCTWebRTC.xcodeproj/project.pbxproj +324 -324
  303. package/macos/RCTWebRTC.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -7
  304. package/macos/RCTWebRTC.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -8
  305. package/metro.config.js +7 -7
  306. package/metro.config.macos.js +14 -14
  307. package/package.json +66 -66
  308. package/react-native.config.js +11 -11
  309. package/src/.eslintrc.cjs +67 -67
  310. package/src/Constraints.ts +20 -20
  311. package/src/EventEmitter.ts +65 -65
  312. package/src/Logger.ts +49 -49
  313. package/src/MediaDevices.ts +53 -53
  314. package/src/MediaStream.ts +161 -161
  315. package/src/MediaStreamError.ts +12 -12
  316. package/src/MediaStreamErrorEvent.ts +11 -11
  317. package/src/MediaStreamTrack.ts +282 -282
  318. package/src/MediaStreamTrackEvent.ts +25 -25
  319. package/src/MessageEvent.ts +26 -26
  320. package/src/Permissions.ts +133 -133
  321. package/src/RTCAudioSession.ts +25 -25
  322. package/src/RTCDataChannel.ts +190 -190
  323. package/src/RTCDataChannelEvent.ts +28 -28
  324. package/src/RTCDataPacketCryptor.ts +90 -90
  325. package/src/RTCDataPacketCryptorFactory.ts +24 -24
  326. package/src/RTCErrorEvent.ts +20 -20
  327. package/src/RTCFrameCryptor.ts +162 -162
  328. package/src/RTCFrameCryptorFactory.ts +101 -101
  329. package/src/RTCIceCandidate.ts +29 -29
  330. package/src/RTCIceCandidateEvent.ts +26 -26
  331. package/src/RTCKeyProvider.ts +117 -117
  332. package/src/RTCPIPView.tsx +46 -46
  333. package/src/RTCPIPView.web.tsx +18 -18
  334. package/src/RTCPeerConnection.ts +935 -935
  335. package/src/RTCRtcpParameters.ts +23 -23
  336. package/src/RTCRtpCapabilities.ts +16 -16
  337. package/src/RTCRtpCodecCapability.ts +12 -12
  338. package/src/RTCRtpCodecParameters.ts +44 -44
  339. package/src/RTCRtpEncodingParameters.ts +90 -90
  340. package/src/RTCRtpHeaderExtension.ts +27 -27
  341. package/src/RTCRtpParameters.ts +37 -37
  342. package/src/RTCRtpReceiveParameters.ts +7 -7
  343. package/src/RTCRtpReceiver.ts +60 -60
  344. package/src/RTCRtpSendParameters.ts +63 -63
  345. package/src/RTCRtpSender.ts +78 -78
  346. package/src/RTCRtpTransceiver.ts +107 -107
  347. package/src/RTCSessionDescription.ts +30 -30
  348. package/src/RTCTrackEvent.ts +42 -42
  349. package/src/RTCUtil.ts +211 -211
  350. package/src/RTCView.ts +122 -122
  351. package/src/RTCView.web.tsx +80 -80
  352. package/src/ScreenCapturePickerView.ts +4 -4
  353. package/src/ScreenCapturePickerView.web.tsx +3 -3
  354. package/src/getDisplayMedia.ts +30 -30
  355. package/src/getUserMedia.ts +136 -136
  356. package/src/index.ts +107 -107
  357. package/src/index.web.ts +191 -191
  358. package/src/webStream.ts +31 -31
  359. package/tools/format.sh +6 -6
  360. package/tools/release.sh +45 -45
  361. package/tsconfig.json +17 -17
@@ -1,1004 +1,1004 @@
1
- #import <objc/runtime.h>
2
-
3
- #import <React/RCTBridge.h>
4
- #import <React/RCTEventDispatcher.h>
5
- #import <React/RCTLog.h>
6
- #import <React/RCTUtils.h>
7
-
8
- #import <WebRTC/RTCConfiguration.h>
9
- #import <WebRTC/RTCIceCandidate.h>
10
- #import <WebRTC/RTCIceServer.h>
11
- #import <WebRTC/RTCMediaConstraints.h>
12
- #import <WebRTC/RTCMediaStreamTrack.h>
13
- #import <WebRTC/RTCRtpReceiver.h>
14
- #import <WebRTC/RTCRtpTransceiver.h>
15
- #import <WebRTC/RTCSessionDescription.h>
16
- #import <WebRTC/RTCStatisticsReport.h>
17
-
18
- #import "SerializeUtils.h"
19
- #import "WebRTCModule+RTCDataChannel.h"
20
- #import "WebRTCModule+RTCPeerConnection.h"
21
- #import "WebRTCModule+VideoTrackAdapter.h"
22
- #import "WebRTCModule.h"
23
- #import "WebRTCModuleOptions.h"
24
-
25
- @implementation RTCPeerConnection (React)
26
-
27
- - (NSMutableDictionary<NSString *, DataChannelWrapper *> *)dataChannels {
28
- return objc_getAssociatedObject(self, _cmd);
29
- }
30
-
31
- - (void)setDataChannels:(NSMutableDictionary<NSString *, DataChannelWrapper *> *)dataChannels {
32
- objc_setAssociatedObject(self, @selector(dataChannels), dataChannels, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
33
- }
34
-
35
- - (NSNumber *)reactTag {
36
- return objc_getAssociatedObject(self, _cmd);
37
- }
38
-
39
- - (void)setReactTag:(NSNumber *)reactTag {
40
- objc_setAssociatedObject(self, @selector(reactTag), reactTag, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
41
- }
42
-
43
- - (NSMutableDictionary<NSString *, RTCMediaStream *> *)remoteStreams {
44
- return objc_getAssociatedObject(self, _cmd);
45
- }
46
-
47
- - (void)setRemoteStreams:(NSMutableDictionary<NSString *, RTCMediaStream *> *)remoteStreams {
48
- objc_setAssociatedObject(self, @selector(remoteStreams), remoteStreams, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
49
- }
50
-
51
- - (NSMutableDictionary<NSString *, RTCMediaStreamTrack *> *)remoteTracks {
52
- return objc_getAssociatedObject(self, _cmd);
53
- }
54
-
55
- - (void)setRemoteTracks:(NSMutableDictionary<NSString *, RTCMediaStreamTrack *> *)remoteTracks {
56
- objc_setAssociatedObject(self, @selector(remoteTracks), remoteTracks, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
57
- }
58
-
59
- - (id)webRTCModule {
60
- return objc_getAssociatedObject(self, _cmd);
61
- }
62
-
63
- - (void)setWebRTCModule:(id)webRTCModule {
64
- objc_setAssociatedObject(self, @selector(webRTCModule), webRTCModule, OBJC_ASSOCIATION_ASSIGN);
65
- }
66
-
67
- @end
68
-
69
- @implementation WebRTCModule (RTCPeerConnection)
70
-
71
- int _transceiverNextId = 0;
72
-
73
- - (nullable RTCRtpSender *)getSenderByPeerConnectionId:(nonnull NSNumber *)peerConnectionId
74
- senderId:(nonnull NSString *)senderId {
75
- RTCPeerConnection *peerConnection = self.peerConnections[peerConnectionId];
76
- if (!peerConnection) {
77
- RCTLogWarn(@"PeerConnection %@ not found", peerConnectionId);
78
- return nil;
79
- }
80
- RTCRtpSender *sender = nil;
81
- for (RTCRtpSender *s in peerConnection.senders) {
82
- if ([senderId isEqual:s.senderId]) {
83
- sender = s;
84
- break;
85
- }
86
- }
87
-
88
- return sender;
89
- }
90
- - (nullable RTCRtpReceiver *)getReceiverByPeerConnectionId:(nonnull NSNumber *)peerConnectionId
91
- receiverId:(nonnull NSString *)receiverId {
92
- RTCPeerConnection *peerConnection = self.peerConnections[peerConnectionId];
93
- if (!peerConnection) {
94
- RCTLogWarn(@"PeerConnection %@ not found", peerConnectionId);
95
- return nil;
96
- }
97
- RTCRtpReceiver *receiver = nil;
98
- for (RTCRtpReceiver *r in peerConnection.receivers) {
99
- if ([receiverId isEqual:r.receiverId]) {
100
- receiver = r;
101
- break;
102
- }
103
- }
104
-
105
- return receiver;
106
- }
107
-
108
- - (nullable RTCRtpTransceiver *)getTransceiverByPeerConnectionId:(nonnull NSNumber *)peerConnectionId
109
- transceiverId:(nonnull NSString *)transceiverId {
110
- RTCPeerConnection *peerConnection = self.peerConnections[peerConnectionId];
111
- if (!peerConnection) {
112
- RCTLogWarn(@"PeerConnection %@ not found", peerConnectionId);
113
- return nil;
114
- }
115
- RTCRtpTransceiver *transceiver = nil;
116
- for (RTCRtpTransceiver *t in peerConnection.transceivers) {
117
- if ([transceiverId isEqual:t.sender.senderId]) {
118
- transceiver = t;
119
- break;
120
- }
121
- }
122
-
123
- return transceiver;
124
- }
125
- /*
126
- * This method is synchronous and blocking. This is done so we can implement createDataChannel
127
- * in the same way (synchronous) since the peer connection needs to exist before.
128
- */
129
- RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(peerConnectionInit
130
- : (RTCConfiguration *)configuration objectID
131
- : (nonnull NSNumber *)objectID) {
132
- __block BOOL ret = YES;
133
-
134
- dispatch_sync(self.workerQueue, ^{
135
- RTCMediaConstraints *constraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:nil
136
- optionalConstraints:nil];
137
- RTCPeerConnection *peerConnection = [self.peerConnectionFactory peerConnectionWithConfiguration:configuration
138
- constraints:constraints
139
- delegate:self];
140
- if (peerConnection == nil) {
141
- ret = NO;
142
- return;
143
- }
144
-
145
- peerConnection.dataChannels = [NSMutableDictionary new];
146
- peerConnection.reactTag = objectID;
147
- peerConnection.remoteStreams = [NSMutableDictionary new];
148
- peerConnection.remoteTracks = [NSMutableDictionary new];
149
- peerConnection.videoTrackAdapters = [NSMutableDictionary new];
150
- peerConnection.webRTCModule = self;
151
-
152
- self.peerConnections[objectID] = peerConnection;
153
- });
154
-
155
- return @(ret);
156
- }
157
-
158
- RCT_EXPORT_METHOD(peerConnectionSetConfiguration
159
- : (RTCConfiguration *)configuration objectID
160
- : (nonnull NSNumber *)objectID) {
161
- RTCPeerConnection *peerConnection = self.peerConnections[objectID];
162
- if (!peerConnection) {
163
- return;
164
- }
165
- [peerConnection setConfiguration:configuration];
166
- }
167
-
168
- RCT_EXPORT_METHOD(peerConnectionCreateOffer
169
- : (nonnull NSNumber *)objectID options
170
- : (NSDictionary *)options resolver
171
- : (RCTPromiseResolveBlock)resolve rejecter
172
- : (RCTPromiseRejectBlock)reject) {
173
- RTCPeerConnection *peerConnection = self.peerConnections[objectID];
174
- if (!peerConnection) {
175
- reject(@"E_INVALID", @"PeerConnection not found", nil);
176
- return;
177
- }
178
-
179
- RTCMediaConstraints *constraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:options
180
- optionalConstraints:nil];
181
-
182
- NSMutableArray *receiversIds = [NSMutableArray new];
183
- for (RTCRtpTransceiver *transceiver in peerConnection.transceivers) {
184
- [receiversIds addObject:transceiver.receiver.receiverId];
185
- }
186
-
187
- RTCCreateSessionDescriptionCompletionHandler handler = ^(RTCSessionDescription *desc, NSError *error) {
188
- dispatch_async(self.workerQueue, ^{
189
- if (error) {
190
- reject(@"E_OPERATION_ERROR", error.localizedDescription, nil);
191
- } else {
192
- NSMutableArray *newTransceivers = [NSMutableArray new];
193
- for (RTCRtpTransceiver *transceiver in peerConnection.transceivers) {
194
- if (![receiversIds containsObject:transceiver.receiver.receiverId]) {
195
- NSMutableDictionary *newTransceiver = [NSMutableDictionary new];
196
- newTransceiver[@"transceiverOrder"] = [NSNumber numberWithInt:_transceiverNextId++];
197
- newTransceiver[@"transceiver"] =
198
- [SerializeUtils transceiverToJSONWithPeerConnectionId:objectID transceiver:transceiver];
199
- [newTransceivers addObject:newTransceiver];
200
- }
201
- }
202
- id data = @{
203
- @"sdpInfo" : @{@"type" : [RTCSessionDescription stringForType:desc.type], @"sdp" : desc.sdp},
204
- @"transceiversInfo" :
205
- [SerializeUtils constructTransceiversInfoArrayWithPeerConnection:peerConnection],
206
- @"newTransceivers" : newTransceivers
207
- };
208
- resolve(data);
209
- }
210
- });
211
- };
212
-
213
- [peerConnection offerForConstraints:constraints completionHandler:handler];
214
- }
215
-
216
- RCT_EXPORT_METHOD(peerConnectionCreateAnswer
217
- : (nonnull NSNumber *)objectID options
218
- : (NSDictionary *)options resolver
219
- : (RCTPromiseResolveBlock)resolve rejecter
220
- : (RCTPromiseRejectBlock)reject) {
221
- RTCPeerConnection *peerConnection = self.peerConnections[objectID];
222
- if (!peerConnection) {
223
- reject(@"E_INVALID", @"PeerConnection not found", nil);
224
- return;
225
- }
226
-
227
- RTCMediaConstraints *constraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:options
228
- optionalConstraints:nil];
229
-
230
- RTCCreateSessionDescriptionCompletionHandler handler = ^(RTCSessionDescription *desc, NSError *error) {
231
- dispatch_async(self.workerQueue, ^{
232
- if (error) {
233
- reject(@"E_OPERATION_ERROR", error.localizedDescription, nil);
234
- } else {
235
- id data = @{
236
- @"sdpInfo" : @{@"type" : [RTCSessionDescription stringForType:desc.type], @"sdp" : desc.sdp},
237
- @"transceiversInfo" :
238
- [SerializeUtils constructTransceiversInfoArrayWithPeerConnection:peerConnection]
239
- };
240
- resolve(data);
241
- }
242
- });
243
- };
244
-
245
- [peerConnection answerForConstraints:constraints completionHandler:handler];
246
- }
247
-
248
- RCT_EXPORT_METHOD(peerConnectionSetLocalDescription
249
- : (nonnull NSNumber *)objectID desc
250
- : (RTCSessionDescription *)desc resolver
251
- : (RCTPromiseResolveBlock)resolve rejecter
252
- : (RCTPromiseRejectBlock)reject) {
253
- RTCPeerConnection *peerConnection = self.peerConnections[objectID];
254
- if (!peerConnection) {
255
- reject(@"E_INVALID", @"PeerConnection not found", nil);
256
- return;
257
- }
258
-
259
- RTCSetSessionDescriptionCompletionHandler handler = ^(NSError *error) {
260
- dispatch_async(self.workerQueue, ^{
261
- if (error) {
262
- reject(@"E_OPERATION_ERROR", error.localizedDescription, nil);
263
- } else {
264
- NSMutableDictionary *sdpInfo = [NSMutableDictionary new];
265
- RTCSessionDescription *localDesc = peerConnection.localDescription;
266
- if (localDesc) {
267
- sdpInfo[@"type"] = [RTCSessionDescription stringForType:localDesc.type];
268
- sdpInfo[@"sdp"] = localDesc.sdp;
269
- }
270
- id data = @{
271
- @"sdpInfo" : sdpInfo,
272
- @"transceiversInfo" :
273
- [SerializeUtils constructTransceiversInfoArrayWithPeerConnection:peerConnection]
274
- };
275
- resolve(data);
276
- }
277
- });
278
- };
279
-
280
- if (desc == nil) {
281
- [peerConnection setLocalDescriptionWithCompletionHandler:handler];
282
- } else {
283
- [peerConnection setLocalDescription:desc completionHandler:handler];
284
- }
285
- }
286
-
287
- RCT_EXPORT_METHOD(peerConnectionSetRemoteDescription
288
- : (nonnull NSNumber *)objectID desc
289
- : (RTCSessionDescription *)desc resolver
290
- : (RCTPromiseResolveBlock)resolve rejecter
291
- : (RCTPromiseRejectBlock)reject) {
292
- RTCPeerConnection *peerConnection = self.peerConnections[objectID];
293
- if (!peerConnection) {
294
- reject(@"E_INVALID", @"PeerConnection not found", nil);
295
- return;
296
- }
297
-
298
- NSMutableArray *receiversIds = [NSMutableArray new];
299
- for (RTCRtpTransceiver *transceiver in peerConnection.transceivers) {
300
- [receiversIds addObject:transceiver.receiver.receiverId];
301
- }
302
-
303
- RTCSetSessionDescriptionCompletionHandler handler = ^(NSError *error) {
304
- dispatch_async(self.workerQueue, ^{
305
- if (error) {
306
- reject(@"E_OPERATION_ERROR", error.localizedDescription, nil);
307
- } else {
308
- NSMutableArray *newTransceivers = [NSMutableArray new];
309
- for (RTCRtpTransceiver *transceiver in peerConnection.transceivers) {
310
- if (![receiversIds containsObject:transceiver.receiver.receiverId]) {
311
- NSMutableDictionary *newTransceiver = [NSMutableDictionary new];
312
- newTransceiver[@"transceiverOrder"] = [NSNumber numberWithInt:_transceiverNextId++];
313
- newTransceiver[@"transceiver"] =
314
- [SerializeUtils transceiverToJSONWithPeerConnectionId:objectID transceiver:transceiver];
315
- [newTransceivers addObject:newTransceiver];
316
- }
317
- }
318
-
319
- NSMutableDictionary *sdpInfo = [NSMutableDictionary new];
320
- RTCSessionDescription *remoteDesc = peerConnection.remoteDescription;
321
- if (remoteDesc) {
322
- sdpInfo[@"type"] = [RTCSessionDescription stringForType:remoteDesc.type];
323
- sdpInfo[@"sdp"] = remoteDesc.sdp;
324
- }
325
- id data = @{
326
- @"sdpInfo" : sdpInfo,
327
- @"transceiversInfo" :
328
- [SerializeUtils constructTransceiversInfoArrayWithPeerConnection:peerConnection],
329
- @"newTransceivers" : newTransceivers
330
- };
331
- resolve(data);
332
- }
333
- });
334
- };
335
-
336
- [peerConnection setRemoteDescription:desc completionHandler:handler];
337
- }
338
-
339
- RCT_EXPORT_METHOD(peerConnectionAddICECandidate
340
- : (nonnull NSNumber *)objectID candidate
341
- : (RTCIceCandidate *)candidate resolver
342
- : (RCTPromiseResolveBlock)resolve rejecter
343
- : (RCTPromiseRejectBlock)reject) {
344
- RTCPeerConnection *peerConnection = self.peerConnections[objectID];
345
- if (!peerConnection) {
346
- reject(@"E_INVALID", @"PeerConnection not found", nil);
347
- return;
348
- }
349
-
350
- id handler = ^(NSError *error) {
351
- dispatch_async(self.workerQueue, ^{
352
- if (error) {
353
- reject(@"E_OPERATION_ERROR", @"addIceCandidate failed", error);
354
- } else {
355
- RTCSessionDescription *remoteDesc = peerConnection.remoteDescription;
356
- id newSdp = @{@"type" : [RTCSessionDescription stringForType:remoteDesc.type], @"sdp" : remoteDesc.sdp};
357
- resolve(newSdp);
358
- }
359
- });
360
- };
361
-
362
- [peerConnection addIceCandidate:candidate completionHandler:handler];
363
- }
364
-
365
- RCT_EXPORT_METHOD(peerConnectionClose : (nonnull NSNumber *)objectID) {
366
- RTCPeerConnection *peerConnection = self.peerConnections[objectID];
367
- if (!peerConnection) {
368
- return;
369
- }
370
-
371
- [peerConnection close];
372
- }
373
-
374
- RCT_EXPORT_METHOD(peerConnectionDispose : (nonnull NSNumber *)objectID) {
375
- RTCPeerConnection *peerConnection = self.peerConnections[objectID];
376
- if (!peerConnection) {
377
- return;
378
- }
379
-
380
- // Remove video track adapters
381
- for (NSString *key in peerConnection.remoteTracks.allKeys) {
382
- RTCMediaStreamTrack *track = peerConnection.remoteTracks[key];
383
- if (track.kind == kRTCMediaStreamTrackKindVideo) {
384
- [peerConnection removeVideoTrackAdapter:(RTCVideoTrack *)track];
385
- }
386
- }
387
-
388
- // Clean up peerConnection's streams and tracks
389
- [peerConnection.remoteStreams removeAllObjects];
390
- [peerConnection.remoteTracks removeAllObjects];
391
-
392
- // Clean up peerConnection's dataChannels.
393
- NSMutableDictionary<NSString *, DataChannelWrapper *> *dataChannels = peerConnection.dataChannels;
394
- for (NSString *tag in dataChannels) {
395
- dataChannels[tag].delegate = nil;
396
- // There is no need to close the RTCDataChannel because it is owned by the
397
- // RTCPeerConnection and the latter will close the former.
398
- }
399
- [dataChannels removeAllObjects];
400
-
401
- [self.peerConnections removeObjectForKey:objectID];
402
- }
403
-
404
- RCT_EXPORT_METHOD(peerConnectionGetStats
405
- : (nonnull NSNumber *)objectID resolver
406
- : (RCTPromiseResolveBlock)resolve rejecter
407
- : (RCTPromiseRejectBlock)reject) {
408
- RTCPeerConnection *peerConnection = self.peerConnections[objectID];
409
- if (!peerConnection) {
410
- RCTLogWarn(@"PeerConnection %@ not found in peerConnectionGetStats()", objectID);
411
- resolve(@"[]");
412
- return;
413
- }
414
-
415
- [peerConnection statisticsWithCompletionHandler:^(RTCStatisticsReport *report) {
416
- resolve([self statsToJSON:report]);
417
- }];
418
- }
419
-
420
- RCT_EXPORT_METHOD(receiverGetStats
421
- : (nonnull NSNumber *)pcId receiverId
422
- : (nonnull NSString *)receiverId resolver
423
- : (RCTPromiseResolveBlock)resolve rejecter
424
- : (RCTPromiseRejectBlock)reject) {
425
- RTCPeerConnection *peerConnection = self.peerConnections[pcId];
426
- if (!peerConnection) {
427
- RCTLogWarn(@"PeerConnection %@ not found in receiverGetStats()", pcId);
428
- resolve(@"[]");
429
- return;
430
- }
431
-
432
- RTCRtpReceiver *receiver;
433
- for (RTCRtpReceiver *findRecv in peerConnection.receivers) {
434
- if ([findRecv.receiverId isEqualToString:receiverId]) {
435
- receiver = findRecv;
436
- break;
437
- }
438
- }
439
-
440
- if (!receiver) {
441
- RCTLogWarn(@"RTCRtpReceiver %@ not found in receiverGetStats()", receiverId);
442
- resolve(@"[]");
443
- return;
444
- }
445
-
446
- [peerConnection statisticsForReceiver:receiver
447
- completionHandler:^(RTCStatisticsReport *report) {
448
- resolve([self statsToJSON:report]);
449
- }];
450
- }
451
-
452
- RCT_EXPORT_METHOD(senderGetStats
453
- : (nonnull NSNumber *)pcId senderId
454
- : (nonnull NSString *)senderId resolver
455
- : (RCTPromiseResolveBlock)resolve rejecter
456
- : (RCTPromiseRejectBlock)reject) {
457
- RTCPeerConnection *peerConnection = self.peerConnections[pcId];
458
- if (!peerConnection) {
459
- RCTLogWarn(@"PeerConnection %@ not found in senderGetStats()", pcId);
460
- resolve(@"[]");
461
- return;
462
- }
463
-
464
- RTCRtpSender *sender;
465
- for (RTCRtpSender *findSend in peerConnection.senders) {
466
- if ([findSend.senderId isEqualToString:senderId]) {
467
- sender = findSend;
468
- break;
469
- }
470
- }
471
-
472
- if (!sender) {
473
- RCTLogWarn(@"RTCRtpSender %@ not found in senderGetStats()", senderId);
474
- resolve(@"[]");
475
- return;
476
- }
477
-
478
- [peerConnection statisticsForSender:sender
479
- completionHandler:^(RTCStatisticsReport *report) {
480
- resolve([self statsToJSON:report]);
481
- }];
482
- }
483
-
484
- RCT_EXPORT_METHOD(peerConnectionRestartIce : (nonnull NSNumber *)objectID) {
485
- RTCPeerConnection *peerConnection = self.peerConnections[objectID];
486
- if (!peerConnection) {
487
- return;
488
- }
489
-
490
- [peerConnection restartIce];
491
- }
492
-
493
- RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(peerConnectionAddTrack
494
- : (nonnull NSNumber *)objectID trackId
495
- : (NSString *)trackId options
496
- : (NSDictionary *)options) {
497
- __block id params = nil;
498
-
499
- dispatch_sync(self.workerQueue, ^{
500
- RTCPeerConnection *peerConnection = self.peerConnections[objectID];
501
- if (!peerConnection) {
502
- RCTLogWarn(@"PeerConnection %@ not found in peerConnectionAddTrack()", objectID);
503
- return;
504
- }
505
-
506
- RTCMediaStreamTrack *track = self.localTracks[trackId];
507
-
508
- NSArray *streamIds = [options objectForKey:@"streamIds"];
509
- RTCRtpSender *sender = [peerConnection addTrack:track streamIds:streamIds];
510
- RTCRtpTransceiver *transceiver = nil;
511
-
512
- for (RTCRtpTransceiver *t in peerConnection.transceivers) {
513
- if ([t.sender.senderId isEqual:sender.senderId]) {
514
- transceiver = t;
515
- break;
516
- }
517
- }
518
-
519
- if (!transceiver) {
520
- RCTLogWarn(@"Transceiver not found in peerConnectionAddTrack()");
521
- return;
522
- }
523
-
524
- params = @{
525
- @"transceiverOrder" : [NSNumber numberWithInt:_transceiverNextId++],
526
- @"transceiver" : [SerializeUtils transceiverToJSONWithPeerConnectionId:objectID transceiver:transceiver],
527
- @"sender" : [SerializeUtils senderToJSONWithPeerConnectionId:objectID sender:sender]
528
- };
529
- });
530
-
531
- return params;
532
- }
533
-
534
- RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(peerConnectionAddTransceiver
535
- : (nonnull NSNumber *)objectID options
536
- : (NSDictionary *)options) {
537
- __block id params = nil;
538
-
539
- dispatch_sync(self.workerQueue, ^{
540
- RTCPeerConnection *peerConnection = self.peerConnections[objectID];
541
- if (!peerConnection) {
542
- RCTLogWarn(@"PeerConnection %@ not found in peerConnectionAddTransceiver()", objectID);
543
- return;
544
- }
545
-
546
- RTCRtpTransceiver *transceiver = nil;
547
- NSString *kind = [options objectForKey:@"type"];
548
- NSString *trackId = [options objectForKey:@"trackId"];
549
- RTCRtpMediaType type = RTCRtpMediaTypeUnsupported;
550
-
551
- if (kind) {
552
- if ([kind isEqual:@"audio"]) {
553
- type = RTCRtpMediaTypeAudio;
554
- } else if ([kind isEqual:@"video"]) {
555
- type = RTCRtpMediaTypeVideo;
556
- }
557
-
558
- NSDictionary *initOptions = [options objectForKey:@"init"];
559
- RTCRtpTransceiverInit *transceiverInit = [SerializeUtils parseTransceiverOptions:initOptions];
560
-
561
- transceiver = [peerConnection addTransceiverOfType:type init:transceiverInit];
562
- } else if (trackId) {
563
- RTCMediaStreamTrack *track = self.localTracks[trackId];
564
-
565
- if (!track) {
566
- track = peerConnection.remoteTracks[trackId];
567
- }
568
-
569
- NSDictionary *initOptions = [options objectForKey:@"init"];
570
- RTCRtpTransceiverInit *transceiverInit = [SerializeUtils parseTransceiverOptions:initOptions];
571
-
572
- transceiver = [peerConnection addTransceiverWithTrack:track init:transceiverInit];
573
- } else {
574
- RCTLogWarn(@"peerConnectionAddTransceiver() no type nor trackId provided in options");
575
- return;
576
- }
577
-
578
- if (transceiver == nil) {
579
- RCTLogWarn(@"peerConnectionAddTransceiver() Error adding transceiver");
580
- return;
581
- }
582
-
583
- params = @{
584
- @"transceiverOrder" : [NSNumber numberWithInt:_transceiverNextId++],
585
- @"transceiver" : [SerializeUtils transceiverToJSONWithPeerConnectionId:objectID transceiver:transceiver]
586
- };
587
- });
588
-
589
- return params;
590
- }
591
-
592
- RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(peerConnectionRemoveTrack
593
- : (nonnull NSNumber *)objectID senderId
594
- : (nonnull NSString *)senderId) {
595
- __block BOOL ret = NO;
596
-
597
- dispatch_sync(self.workerQueue, ^{
598
- RTCPeerConnection *peerConnection = self.peerConnections[objectID];
599
- if (!peerConnection) {
600
- RCTLogWarn(@"PeerConnection %@ not found in peerConnectionRemoveTrack()", objectID);
601
- return;
602
- }
603
-
604
- RTCRtpSender *sender = nil;
605
-
606
- for (RTCRtpSender *s in peerConnection.senders) {
607
- if ([s.senderId isEqual:senderId]) {
608
- sender = s;
609
- break;
610
- }
611
- }
612
-
613
- if (!sender) {
614
- RCTLogWarn(@"Sender not found in peerConnectionRemoveTrack()");
615
- return;
616
- }
617
-
618
- ret = [peerConnection removeTrack:sender];
619
- });
620
-
621
- return @(ret);
622
- }
623
-
624
- // TODO: move these below to some SerializeUtils file
625
-
626
- /**
627
- * Constructs a JSON <tt>NSString</tt> representation of a specific
628
- * <tt>RTCStatisticsReport</tt>s.
629
- * <p>
630
- *
631
- * @param <tt>RTCStatisticsReport</tt>s
632
- * @return an <tt>NSString</tt> which represents the specified <tt>report</tt> in
633
- * JSON format
634
- */
635
- - (NSString *)statsToJSON:(RTCStatisticsReport *)report {
636
- /*
637
- The initial capacity matters, of course, because it determines how many
638
- times the NSMutableString will have grow. But walking through the reports
639
- to compute an initial capacity which exactly matches the requirements of
640
- the reports is too much work without real-world bang here. An improvement
641
- should be caching the required capacity from the previous invocation of the
642
- method and using it as the initial capacity in the next invocation.
643
- As I didn't want to go even through that,choosing just about any initial
644
- capacity is OK because NSMutableCopy doesn't have too bad a strategy of growing.
645
- */
646
- NSMutableString *s = [NSMutableString stringWithCapacity:16 * 1024];
647
-
648
- [s appendString:@"["];
649
- BOOL firstReport = YES;
650
- for (NSString *key in report.statistics.allKeys) {
651
- if (firstReport) {
652
- firstReport = NO;
653
- } else {
654
- [s appendString:@","];
655
- }
656
-
657
- [s appendString:@"[\""];
658
- [s appendString:key];
659
- [s appendString:@"\",{"];
660
-
661
- RTCStatistics *statistics = report.statistics[key];
662
- [s appendString:@"\"timestamp\":"];
663
- [s appendFormat:@"%f", statistics.timestamp_us / 1000.0];
664
- [s appendString:@",\"type\":\""];
665
- [s appendString:statistics.type];
666
- [s appendString:@"\",\"id\":\""];
667
- [s appendString:statistics.id];
668
- [s appendString:@"\""];
669
-
670
- for (id key in statistics.values) {
671
- [s appendString:@","];
672
- [s appendString:@"\""];
673
- [s appendString:key];
674
- [s appendString:@"\":"];
675
- NSObject *statisticsValue = [statistics.values objectForKey:key];
676
- [self appendValue:statisticsValue toString:s];
677
- }
678
-
679
- [s appendString:@"}]"];
680
- }
681
-
682
- [s appendString:@"]"];
683
-
684
- return s;
685
- }
686
-
687
- - (void)appendValue:(NSObject *)statisticsValue toString:(NSMutableString *)s {
688
- if ([statisticsValue isKindOfClass:[NSArray class]]) {
689
- [s appendString:@"["];
690
- BOOL firstValue = YES;
691
- for (NSObject *element in (NSArray *)statisticsValue) {
692
- if (firstValue) {
693
- firstValue = NO;
694
- } else {
695
- [s appendString:@","];
696
- }
697
-
698
- [s appendString:@"\""];
699
- [s appendString:[NSString stringWithFormat:@"%@", element]];
700
- [s appendString:@"\""];
701
- }
702
-
703
- [s appendString:@"]"];
704
- } else if ([statisticsValue isKindOfClass:[NSDictionary class]]) {
705
- NSError *error;
706
- NSData *jsonData = [NSJSONSerialization dataWithJSONObject:statisticsValue options:0 error:&error];
707
-
708
- if (!jsonData) {
709
- [s appendString:@"\""];
710
- [s appendString:[NSString stringWithFormat:@"%@", statisticsValue]];
711
- [s appendString:@"\""];
712
- } else {
713
- NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
714
- [s appendString:jsonString];
715
- }
716
- } else if ([statisticsValue isKindOfClass:[NSNumber class]]) {
717
- [s appendString:[NSString stringWithFormat:@"%@", statisticsValue]];
718
- } else {
719
- [s appendString:@"\""];
720
- [s appendString:[NSString stringWithFormat:@"%@", statisticsValue]];
721
- [s appendString:@"\""];
722
- }
723
- }
724
-
725
- - (NSString *)stringForPeerConnectionState:(RTCPeerConnectionState)state {
726
- switch (state) {
727
- case RTCPeerConnectionStateNew:
728
- return @"new";
729
- case RTCPeerConnectionStateConnecting:
730
- return @"connecting";
731
- case RTCPeerConnectionStateConnected:
732
- return @"connected";
733
- case RTCPeerConnectionStateDisconnected:
734
- return @"disconnected";
735
- case RTCPeerConnectionStateFailed:
736
- return @"failed";
737
- case RTCPeerConnectionStateClosed:
738
- return @"closed";
739
- }
740
- return nil;
741
- }
742
-
743
- - (NSString *)stringForICEConnectionState:(RTCIceConnectionState)state {
744
- switch (state) {
745
- case RTCIceConnectionStateNew:
746
- return @"new";
747
- case RTCIceConnectionStateChecking:
748
- return @"checking";
749
- case RTCIceConnectionStateConnected:
750
- return @"connected";
751
- case RTCIceConnectionStateCompleted:
752
- return @"completed";
753
- case RTCIceConnectionStateFailed:
754
- return @"failed";
755
- case RTCIceConnectionStateDisconnected:
756
- return @"disconnected";
757
- case RTCIceConnectionStateClosed:
758
- return @"closed";
759
- case RTCIceConnectionStateCount:
760
- return @"count";
761
- }
762
- return nil;
763
- }
764
-
765
- - (NSString *)stringForICEGatheringState:(RTCIceGatheringState)state {
766
- switch (state) {
767
- case RTCIceGatheringStateNew:
768
- return @"new";
769
- case RTCIceGatheringStateGathering:
770
- return @"gathering";
771
- case RTCIceGatheringStateComplete:
772
- return @"complete";
773
- }
774
- return nil;
775
- }
776
-
777
- - (NSString *)stringForSignalingState:(RTCSignalingState)state {
778
- switch (state) {
779
- case RTCSignalingStateStable:
780
- return @"stable";
781
- case RTCSignalingStateHaveLocalOffer:
782
- return @"have-local-offer";
783
- case RTCSignalingStateHaveLocalPrAnswer:
784
- return @"have-local-pranswer";
785
- case RTCSignalingStateHaveRemoteOffer:
786
- return @"have-remote-offer";
787
- case RTCSignalingStateHaveRemotePrAnswer:
788
- return @"have-remote-pranswer";
789
- case RTCSignalingStateClosed:
790
- return @"closed";
791
- }
792
- return nil;
793
- }
794
-
795
- #pragma mark - RTCPeerConnectionDelegate methods
796
-
797
- - (void)peerConnection:(RTCPeerConnection *)peerConnection didChangeSignalingState:(RTCSignalingState)newState {
798
- dispatch_async(self.workerQueue, ^{
799
- [self sendEventWithName:kEventPeerConnectionSignalingStateChanged
800
- body:@{
801
- @"pcId" : peerConnection.reactTag,
802
- @"signalingState" : [self stringForSignalingState:newState]
803
- }];
804
- });
805
- }
806
-
807
- - (void)peerConnectionShouldNegotiate:(RTCPeerConnection *)peerConnection {
808
- dispatch_async(self.workerQueue, ^{
809
- [self sendEventWithName:kEventPeerConnectionOnRenegotiationNeeded body:@{@"pcId" : peerConnection.reactTag}];
810
- });
811
- }
812
-
813
- - (void)peerConnection:(RTCPeerConnection *)peerConnection didChangeConnectionState:(RTCPeerConnectionState)newState {
814
- dispatch_async(self.workerQueue, ^{
815
- [self sendEventWithName:kEventPeerConnectionStateChanged
816
- body:@{
817
- @"pcId" : peerConnection.reactTag,
818
- @"connectionState" : [self stringForPeerConnectionState:newState]
819
- }];
820
- });
821
- }
822
-
823
- - (void)peerConnection:(RTCPeerConnection *)peerConnection didChangeIceConnectionState:(RTCIceConnectionState)newState {
824
- dispatch_async(self.workerQueue, ^{
825
- [self sendEventWithName:kEventPeerConnectionIceConnectionChanged
826
- body:@{
827
- @"pcId" : peerConnection.reactTag,
828
- @"iceConnectionState" : [self stringForICEConnectionState:newState]
829
- }];
830
- });
831
- }
832
-
833
- - (void)peerConnection:(RTCPeerConnection *)peerConnection didChangeIceGatheringState:(RTCIceGatheringState)newState {
834
- dispatch_async(self.workerQueue, ^{
835
- id newSdp = @{};
836
- if (newState == RTCIceGatheringStateComplete) {
837
- // Can happen when doing a rollback.
838
- if (peerConnection.localDescription) {
839
- newSdp = @{
840
- @"type" : [RTCSessionDescription stringForType:peerConnection.localDescription.type],
841
- @"sdp" : peerConnection.localDescription.sdp
842
- };
843
- }
844
- }
845
-
846
- [self sendEventWithName:kEventPeerConnectionIceGatheringChanged
847
- body:@{
848
- @"pcId" : peerConnection.reactTag,
849
- @"iceGatheringState" : [self stringForICEGatheringState:newState],
850
- @"sdp" : newSdp
851
- }];
852
- });
853
- }
854
-
855
- - (void)peerConnection:(RTCPeerConnection *)peerConnection didGenerateIceCandidate:(RTCIceCandidate *)candidate {
856
- dispatch_async(self.workerQueue, ^{
857
- id newSdp = @{};
858
- // Can happen when doing a rollback.
859
- if (peerConnection.localDescription) {
860
- newSdp = @{
861
- @"type" : [RTCSessionDescription stringForType:peerConnection.localDescription.type],
862
- @"sdp" : peerConnection.localDescription.sdp
863
- };
864
- }
865
-
866
- [self sendEventWithName:kEventPeerConnectionGotICECandidate
867
- body:@{
868
- @"pcId" : peerConnection.reactTag,
869
- @"candidate" : @{
870
- @"candidate" : candidate.sdp,
871
- @"sdpMLineIndex" : @(candidate.sdpMLineIndex),
872
- @"sdpMid" : candidate.sdpMid
873
- },
874
- @"sdp" : newSdp
875
- }];
876
- });
877
- }
878
-
879
- - (void)peerConnection:(RTCPeerConnection *)peerConnection didOpenDataChannel:(RTCDataChannel *)dataChannel {
880
- dispatch_async(self.workerQueue, ^{
881
- NSString *reactTag = [[NSUUID UUID] UUIDString];
882
- DataChannelWrapper *dcw = [[DataChannelWrapper alloc] initWithChannel:dataChannel reactTag:reactTag];
883
- dcw.pcId = peerConnection.reactTag;
884
- peerConnection.dataChannels[reactTag] = dcw;
885
- dcw.delegate = self;
886
-
887
- NSDictionary *dataChannelInfo = @{
888
- @"peerConnectionId" : peerConnection.reactTag,
889
- @"reactTag" : reactTag,
890
- @"label" : dataChannel.label,
891
- @"id" : @(dataChannel.channelId),
892
- @"ordered" : @(dataChannel.isOrdered),
893
- @"maxPacketLifeTime" : @(dataChannel.maxPacketLifeTime),
894
- @"maxRetransmits" : @(dataChannel.maxRetransmits),
895
- @"protocol" : dataChannel.protocol,
896
- @"negotiated" : @(dataChannel.isNegotiated),
897
- @"readyState" : [self stringForDataChannelState:dataChannel.readyState]
898
- };
899
- NSDictionary *body = @{@"pcId" : peerConnection.reactTag, @"dataChannel" : dataChannelInfo};
900
-
901
- [self sendEventWithName:kEventPeerConnectionDidOpenDataChannel body:body];
902
- });
903
- }
904
-
905
- - (void)peerConnection:(RTC_OBJC_TYPE(RTCPeerConnection) *)peerConnection
906
- didAddReceiver:(RTC_OBJC_TYPE(RTCRtpReceiver) *)rtpReceiver
907
- streams:(NSArray<RTC_OBJC_TYPE(RTCMediaStream) *> *)mediaStreams {
908
- dispatch_async(self.workerQueue, ^{
909
- RTCRtpTransceiver *transceiver = nil;
910
- for (RTCRtpTransceiver *t in peerConnection.transceivers) {
911
- if ([rtpReceiver.receiverId isEqual:t.receiver.receiverId]) {
912
- transceiver = t;
913
- break;
914
- }
915
- }
916
-
917
- if (!transceiver) {
918
- RCTLogWarn(@"Transceiver not found in didAddReceiver()");
919
- return;
920
- }
921
-
922
- RTCMediaStreamTrack *track = rtpReceiver.track;
923
-
924
- // We need to fire this event for an existing track sometimes, like
925
- // when the transceiver direction (on the sending side) switches from
926
- // sendrecv to recvonly and then back.
927
- BOOL existingTrack = peerConnection.remoteTracks[track.trackId] != nil;
928
-
929
- if (!existingTrack) {
930
- if (track.kind == kRTCMediaStreamTrackKindVideo) {
931
- RTCVideoTrack *videoTrack = (RTCVideoTrack *)track;
932
- [peerConnection addVideoTrackAdapter:videoTrack];
933
- } else if (track.kind == kRTCMediaStreamTrackKindAudio) {
934
- RTCAudioTrack *audioTrack = (RTCAudioTrack *)track;
935
- WebRTCModuleOptions *options = [WebRTCModuleOptions sharedInstance];
936
- audioTrack.source.volume = options.defaultTrackVolume;
937
- }
938
-
939
- peerConnection.remoteTracks[track.trackId] = track;
940
- }
941
-
942
- NSMutableDictionary *params = [NSMutableDictionary new];
943
- NSMutableArray *streams = [NSMutableArray new];
944
-
945
- for (RTCMediaStream *stream in mediaStreams) {
946
- NSString *streamReactTag = nil;
947
-
948
- for (NSString *key in [peerConnection.remoteStreams allKeys]) {
949
- if ([[peerConnection.remoteStreams objectForKey:key].streamId isEqual:stream.streamId]) {
950
- streamReactTag = key;
951
- break;
952
- }
953
- }
954
-
955
- if (!streamReactTag) {
956
- streamReactTag = [[NSUUID UUID] UUIDString];
957
- }
958
-
959
- // Make sure the stored stream is updated in case we get a new reference.
960
- peerConnection.remoteStreams[streamReactTag] = stream;
961
-
962
- [streams addObject:[SerializeUtils streamToJSONWithPeerConnectionId:peerConnection.reactTag
963
- stream:stream
964
- streamReactTag:streamReactTag]];
965
- }
966
-
967
- params[@"streams"] = streams;
968
- params[@"receiver"] = [SerializeUtils receiverToJSONWithPeerConnectionId:peerConnection.reactTag
969
- receiver:rtpReceiver];
970
- params[@"transceiverOrder"] = [NSNumber numberWithInt:_transceiverNextId++];
971
- params[@"transceiver"] = [SerializeUtils transceiverToJSONWithPeerConnectionId:peerConnection.reactTag
972
- transceiver:transceiver];
973
- params[@"pcId"] = peerConnection.reactTag;
974
-
975
- [self sendEventWithName:kEventPeerConnectionOnTrack body:params];
976
- });
977
- }
978
-
979
- - (void)peerConnection:(RTC_OBJC_TYPE(RTCPeerConnection) *)peerConnection
980
- didRemoveReceiver:(RTC_OBJC_TYPE(RTCRtpReceiver) *)rtpReceiver {
981
- dispatch_async(self.workerQueue, ^{
982
- NSMutableDictionary *params = [NSMutableDictionary new];
983
-
984
- params[@"pcId"] = peerConnection.reactTag;
985
- params[@"receiverId"] = rtpReceiver.receiverId;
986
-
987
- [self sendEventWithName:kEventPeerConnectionOnRemoveTrack body:params];
988
- });
989
- }
990
-
991
- - (void)peerConnection:(nonnull RTCPeerConnection *)peerConnection
992
- didRemoveIceCandidates:(nonnull NSArray<RTCIceCandidate *> *)candidates {
993
- // Unimplemented, there is no matching web API.
994
- }
995
-
996
- - (void)peerConnection:(nonnull RTCPeerConnection *)peerConnection didAddStream:(nonnull RTCMediaStream *)stream {
997
- // Unused in Unified Plan.
998
- }
999
-
1000
- - (void)peerConnection:(nonnull RTCPeerConnection *)peerConnection didRemoveStream:(nonnull RTCMediaStream *)stream {
1001
- // Unused in Unified Plan.
1002
- }
1003
-
1004
- @end
1
+ #import <objc/runtime.h>
2
+
3
+ #import <React/RCTBridge.h>
4
+ #import <React/RCTEventDispatcher.h>
5
+ #import <React/RCTLog.h>
6
+ #import <React/RCTUtils.h>
7
+
8
+ #import <WebRTC/RTCConfiguration.h>
9
+ #import <WebRTC/RTCIceCandidate.h>
10
+ #import <WebRTC/RTCIceServer.h>
11
+ #import <WebRTC/RTCMediaConstraints.h>
12
+ #import <WebRTC/RTCMediaStreamTrack.h>
13
+ #import <WebRTC/RTCRtpReceiver.h>
14
+ #import <WebRTC/RTCRtpTransceiver.h>
15
+ #import <WebRTC/RTCSessionDescription.h>
16
+ #import <WebRTC/RTCStatisticsReport.h>
17
+
18
+ #import "SerializeUtils.h"
19
+ #import "WebRTCModule+RTCDataChannel.h"
20
+ #import "WebRTCModule+RTCPeerConnection.h"
21
+ #import "WebRTCModule+VideoTrackAdapter.h"
22
+ #import "WebRTCModule.h"
23
+ #import "WebRTCModuleOptions.h"
24
+
25
+ @implementation RTCPeerConnection (React)
26
+
27
+ - (NSMutableDictionary<NSString *, DataChannelWrapper *> *)dataChannels {
28
+ return objc_getAssociatedObject(self, _cmd);
29
+ }
30
+
31
+ - (void)setDataChannels:(NSMutableDictionary<NSString *, DataChannelWrapper *> *)dataChannels {
32
+ objc_setAssociatedObject(self, @selector(dataChannels), dataChannels, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
33
+ }
34
+
35
+ - (NSNumber *)reactTag {
36
+ return objc_getAssociatedObject(self, _cmd);
37
+ }
38
+
39
+ - (void)setReactTag:(NSNumber *)reactTag {
40
+ objc_setAssociatedObject(self, @selector(reactTag), reactTag, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
41
+ }
42
+
43
+ - (NSMutableDictionary<NSString *, RTCMediaStream *> *)remoteStreams {
44
+ return objc_getAssociatedObject(self, _cmd);
45
+ }
46
+
47
+ - (void)setRemoteStreams:(NSMutableDictionary<NSString *, RTCMediaStream *> *)remoteStreams {
48
+ objc_setAssociatedObject(self, @selector(remoteStreams), remoteStreams, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
49
+ }
50
+
51
+ - (NSMutableDictionary<NSString *, RTCMediaStreamTrack *> *)remoteTracks {
52
+ return objc_getAssociatedObject(self, _cmd);
53
+ }
54
+
55
+ - (void)setRemoteTracks:(NSMutableDictionary<NSString *, RTCMediaStreamTrack *> *)remoteTracks {
56
+ objc_setAssociatedObject(self, @selector(remoteTracks), remoteTracks, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
57
+ }
58
+
59
+ - (id)webRTCModule {
60
+ return objc_getAssociatedObject(self, _cmd);
61
+ }
62
+
63
+ - (void)setWebRTCModule:(id)webRTCModule {
64
+ objc_setAssociatedObject(self, @selector(webRTCModule), webRTCModule, OBJC_ASSOCIATION_ASSIGN);
65
+ }
66
+
67
+ @end
68
+
69
+ @implementation WebRTCModule (RTCPeerConnection)
70
+
71
+ int _transceiverNextId = 0;
72
+
73
+ - (nullable RTCRtpSender *)getSenderByPeerConnectionId:(nonnull NSNumber *)peerConnectionId
74
+ senderId:(nonnull NSString *)senderId {
75
+ RTCPeerConnection *peerConnection = self.peerConnections[peerConnectionId];
76
+ if (!peerConnection) {
77
+ RCTLogWarn(@"PeerConnection %@ not found", peerConnectionId);
78
+ return nil;
79
+ }
80
+ RTCRtpSender *sender = nil;
81
+ for (RTCRtpSender *s in peerConnection.senders) {
82
+ if ([senderId isEqual:s.senderId]) {
83
+ sender = s;
84
+ break;
85
+ }
86
+ }
87
+
88
+ return sender;
89
+ }
90
+ - (nullable RTCRtpReceiver *)getReceiverByPeerConnectionId:(nonnull NSNumber *)peerConnectionId
91
+ receiverId:(nonnull NSString *)receiverId {
92
+ RTCPeerConnection *peerConnection = self.peerConnections[peerConnectionId];
93
+ if (!peerConnection) {
94
+ RCTLogWarn(@"PeerConnection %@ not found", peerConnectionId);
95
+ return nil;
96
+ }
97
+ RTCRtpReceiver *receiver = nil;
98
+ for (RTCRtpReceiver *r in peerConnection.receivers) {
99
+ if ([receiverId isEqual:r.receiverId]) {
100
+ receiver = r;
101
+ break;
102
+ }
103
+ }
104
+
105
+ return receiver;
106
+ }
107
+
108
+ - (nullable RTCRtpTransceiver *)getTransceiverByPeerConnectionId:(nonnull NSNumber *)peerConnectionId
109
+ transceiverId:(nonnull NSString *)transceiverId {
110
+ RTCPeerConnection *peerConnection = self.peerConnections[peerConnectionId];
111
+ if (!peerConnection) {
112
+ RCTLogWarn(@"PeerConnection %@ not found", peerConnectionId);
113
+ return nil;
114
+ }
115
+ RTCRtpTransceiver *transceiver = nil;
116
+ for (RTCRtpTransceiver *t in peerConnection.transceivers) {
117
+ if ([transceiverId isEqual:t.sender.senderId]) {
118
+ transceiver = t;
119
+ break;
120
+ }
121
+ }
122
+
123
+ return transceiver;
124
+ }
125
+ /*
126
+ * This method is synchronous and blocking. This is done so we can implement createDataChannel
127
+ * in the same way (synchronous) since the peer connection needs to exist before.
128
+ */
129
+ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(peerConnectionInit
130
+ : (RTCConfiguration *)configuration objectID
131
+ : (nonnull NSNumber *)objectID) {
132
+ __block BOOL ret = YES;
133
+
134
+ dispatch_sync(self.workerQueue, ^{
135
+ RTCMediaConstraints *constraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:nil
136
+ optionalConstraints:nil];
137
+ RTCPeerConnection *peerConnection = [self.peerConnectionFactory peerConnectionWithConfiguration:configuration
138
+ constraints:constraints
139
+ delegate:self];
140
+ if (peerConnection == nil) {
141
+ ret = NO;
142
+ return;
143
+ }
144
+
145
+ peerConnection.dataChannels = [NSMutableDictionary new];
146
+ peerConnection.reactTag = objectID;
147
+ peerConnection.remoteStreams = [NSMutableDictionary new];
148
+ peerConnection.remoteTracks = [NSMutableDictionary new];
149
+ peerConnection.videoTrackAdapters = [NSMutableDictionary new];
150
+ peerConnection.webRTCModule = self;
151
+
152
+ self.peerConnections[objectID] = peerConnection;
153
+ });
154
+
155
+ return @(ret);
156
+ }
157
+
158
+ RCT_EXPORT_METHOD(peerConnectionSetConfiguration
159
+ : (RTCConfiguration *)configuration objectID
160
+ : (nonnull NSNumber *)objectID) {
161
+ RTCPeerConnection *peerConnection = self.peerConnections[objectID];
162
+ if (!peerConnection) {
163
+ return;
164
+ }
165
+ [peerConnection setConfiguration:configuration];
166
+ }
167
+
168
+ RCT_EXPORT_METHOD(peerConnectionCreateOffer
169
+ : (nonnull NSNumber *)objectID options
170
+ : (NSDictionary *)options resolver
171
+ : (RCTPromiseResolveBlock)resolve rejecter
172
+ : (RCTPromiseRejectBlock)reject) {
173
+ RTCPeerConnection *peerConnection = self.peerConnections[objectID];
174
+ if (!peerConnection) {
175
+ reject(@"E_INVALID", @"PeerConnection not found", nil);
176
+ return;
177
+ }
178
+
179
+ RTCMediaConstraints *constraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:options
180
+ optionalConstraints:nil];
181
+
182
+ NSMutableArray *receiversIds = [NSMutableArray new];
183
+ for (RTCRtpTransceiver *transceiver in peerConnection.transceivers) {
184
+ [receiversIds addObject:transceiver.receiver.receiverId];
185
+ }
186
+
187
+ RTCCreateSessionDescriptionCompletionHandler handler = ^(RTCSessionDescription *desc, NSError *error) {
188
+ dispatch_async(self.workerQueue, ^{
189
+ if (error) {
190
+ reject(@"E_OPERATION_ERROR", error.localizedDescription, nil);
191
+ } else {
192
+ NSMutableArray *newTransceivers = [NSMutableArray new];
193
+ for (RTCRtpTransceiver *transceiver in peerConnection.transceivers) {
194
+ if (![receiversIds containsObject:transceiver.receiver.receiverId]) {
195
+ NSMutableDictionary *newTransceiver = [NSMutableDictionary new];
196
+ newTransceiver[@"transceiverOrder"] = [NSNumber numberWithInt:_transceiverNextId++];
197
+ newTransceiver[@"transceiver"] =
198
+ [SerializeUtils transceiverToJSONWithPeerConnectionId:objectID transceiver:transceiver];
199
+ [newTransceivers addObject:newTransceiver];
200
+ }
201
+ }
202
+ id data = @{
203
+ @"sdpInfo" : @{@"type" : [RTCSessionDescription stringForType:desc.type], @"sdp" : desc.sdp},
204
+ @"transceiversInfo" :
205
+ [SerializeUtils constructTransceiversInfoArrayWithPeerConnection:peerConnection],
206
+ @"newTransceivers" : newTransceivers
207
+ };
208
+ resolve(data);
209
+ }
210
+ });
211
+ };
212
+
213
+ [peerConnection offerForConstraints:constraints completionHandler:handler];
214
+ }
215
+
216
+ RCT_EXPORT_METHOD(peerConnectionCreateAnswer
217
+ : (nonnull NSNumber *)objectID options
218
+ : (NSDictionary *)options resolver
219
+ : (RCTPromiseResolveBlock)resolve rejecter
220
+ : (RCTPromiseRejectBlock)reject) {
221
+ RTCPeerConnection *peerConnection = self.peerConnections[objectID];
222
+ if (!peerConnection) {
223
+ reject(@"E_INVALID", @"PeerConnection not found", nil);
224
+ return;
225
+ }
226
+
227
+ RTCMediaConstraints *constraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:options
228
+ optionalConstraints:nil];
229
+
230
+ RTCCreateSessionDescriptionCompletionHandler handler = ^(RTCSessionDescription *desc, NSError *error) {
231
+ dispatch_async(self.workerQueue, ^{
232
+ if (error) {
233
+ reject(@"E_OPERATION_ERROR", error.localizedDescription, nil);
234
+ } else {
235
+ id data = @{
236
+ @"sdpInfo" : @{@"type" : [RTCSessionDescription stringForType:desc.type], @"sdp" : desc.sdp},
237
+ @"transceiversInfo" :
238
+ [SerializeUtils constructTransceiversInfoArrayWithPeerConnection:peerConnection]
239
+ };
240
+ resolve(data);
241
+ }
242
+ });
243
+ };
244
+
245
+ [peerConnection answerForConstraints:constraints completionHandler:handler];
246
+ }
247
+
248
+ RCT_EXPORT_METHOD(peerConnectionSetLocalDescription
249
+ : (nonnull NSNumber *)objectID desc
250
+ : (RTCSessionDescription *)desc resolver
251
+ : (RCTPromiseResolveBlock)resolve rejecter
252
+ : (RCTPromiseRejectBlock)reject) {
253
+ RTCPeerConnection *peerConnection = self.peerConnections[objectID];
254
+ if (!peerConnection) {
255
+ reject(@"E_INVALID", @"PeerConnection not found", nil);
256
+ return;
257
+ }
258
+
259
+ RTCSetSessionDescriptionCompletionHandler handler = ^(NSError *error) {
260
+ dispatch_async(self.workerQueue, ^{
261
+ if (error) {
262
+ reject(@"E_OPERATION_ERROR", error.localizedDescription, nil);
263
+ } else {
264
+ NSMutableDictionary *sdpInfo = [NSMutableDictionary new];
265
+ RTCSessionDescription *localDesc = peerConnection.localDescription;
266
+ if (localDesc) {
267
+ sdpInfo[@"type"] = [RTCSessionDescription stringForType:localDesc.type];
268
+ sdpInfo[@"sdp"] = localDesc.sdp;
269
+ }
270
+ id data = @{
271
+ @"sdpInfo" : sdpInfo,
272
+ @"transceiversInfo" :
273
+ [SerializeUtils constructTransceiversInfoArrayWithPeerConnection:peerConnection]
274
+ };
275
+ resolve(data);
276
+ }
277
+ });
278
+ };
279
+
280
+ if (desc == nil) {
281
+ [peerConnection setLocalDescriptionWithCompletionHandler:handler];
282
+ } else {
283
+ [peerConnection setLocalDescription:desc completionHandler:handler];
284
+ }
285
+ }
286
+
287
+ RCT_EXPORT_METHOD(peerConnectionSetRemoteDescription
288
+ : (nonnull NSNumber *)objectID desc
289
+ : (RTCSessionDescription *)desc resolver
290
+ : (RCTPromiseResolveBlock)resolve rejecter
291
+ : (RCTPromiseRejectBlock)reject) {
292
+ RTCPeerConnection *peerConnection = self.peerConnections[objectID];
293
+ if (!peerConnection) {
294
+ reject(@"E_INVALID", @"PeerConnection not found", nil);
295
+ return;
296
+ }
297
+
298
+ NSMutableArray *receiversIds = [NSMutableArray new];
299
+ for (RTCRtpTransceiver *transceiver in peerConnection.transceivers) {
300
+ [receiversIds addObject:transceiver.receiver.receiverId];
301
+ }
302
+
303
+ RTCSetSessionDescriptionCompletionHandler handler = ^(NSError *error) {
304
+ dispatch_async(self.workerQueue, ^{
305
+ if (error) {
306
+ reject(@"E_OPERATION_ERROR", error.localizedDescription, nil);
307
+ } else {
308
+ NSMutableArray *newTransceivers = [NSMutableArray new];
309
+ for (RTCRtpTransceiver *transceiver in peerConnection.transceivers) {
310
+ if (![receiversIds containsObject:transceiver.receiver.receiverId]) {
311
+ NSMutableDictionary *newTransceiver = [NSMutableDictionary new];
312
+ newTransceiver[@"transceiverOrder"] = [NSNumber numberWithInt:_transceiverNextId++];
313
+ newTransceiver[@"transceiver"] =
314
+ [SerializeUtils transceiverToJSONWithPeerConnectionId:objectID transceiver:transceiver];
315
+ [newTransceivers addObject:newTransceiver];
316
+ }
317
+ }
318
+
319
+ NSMutableDictionary *sdpInfo = [NSMutableDictionary new];
320
+ RTCSessionDescription *remoteDesc = peerConnection.remoteDescription;
321
+ if (remoteDesc) {
322
+ sdpInfo[@"type"] = [RTCSessionDescription stringForType:remoteDesc.type];
323
+ sdpInfo[@"sdp"] = remoteDesc.sdp;
324
+ }
325
+ id data = @{
326
+ @"sdpInfo" : sdpInfo,
327
+ @"transceiversInfo" :
328
+ [SerializeUtils constructTransceiversInfoArrayWithPeerConnection:peerConnection],
329
+ @"newTransceivers" : newTransceivers
330
+ };
331
+ resolve(data);
332
+ }
333
+ });
334
+ };
335
+
336
+ [peerConnection setRemoteDescription:desc completionHandler:handler];
337
+ }
338
+
339
+ RCT_EXPORT_METHOD(peerConnectionAddICECandidate
340
+ : (nonnull NSNumber *)objectID candidate
341
+ : (RTCIceCandidate *)candidate resolver
342
+ : (RCTPromiseResolveBlock)resolve rejecter
343
+ : (RCTPromiseRejectBlock)reject) {
344
+ RTCPeerConnection *peerConnection = self.peerConnections[objectID];
345
+ if (!peerConnection) {
346
+ reject(@"E_INVALID", @"PeerConnection not found", nil);
347
+ return;
348
+ }
349
+
350
+ id handler = ^(NSError *error) {
351
+ dispatch_async(self.workerQueue, ^{
352
+ if (error) {
353
+ reject(@"E_OPERATION_ERROR", @"addIceCandidate failed", error);
354
+ } else {
355
+ RTCSessionDescription *remoteDesc = peerConnection.remoteDescription;
356
+ id newSdp = @{@"type" : [RTCSessionDescription stringForType:remoteDesc.type], @"sdp" : remoteDesc.sdp};
357
+ resolve(newSdp);
358
+ }
359
+ });
360
+ };
361
+
362
+ [peerConnection addIceCandidate:candidate completionHandler:handler];
363
+ }
364
+
365
+ RCT_EXPORT_METHOD(peerConnectionClose : (nonnull NSNumber *)objectID) {
366
+ RTCPeerConnection *peerConnection = self.peerConnections[objectID];
367
+ if (!peerConnection) {
368
+ return;
369
+ }
370
+
371
+ [peerConnection close];
372
+ }
373
+
374
+ RCT_EXPORT_METHOD(peerConnectionDispose : (nonnull NSNumber *)objectID) {
375
+ RTCPeerConnection *peerConnection = self.peerConnections[objectID];
376
+ if (!peerConnection) {
377
+ return;
378
+ }
379
+
380
+ // Remove video track adapters
381
+ for (NSString *key in peerConnection.remoteTracks.allKeys) {
382
+ RTCMediaStreamTrack *track = peerConnection.remoteTracks[key];
383
+ if (track.kind == kRTCMediaStreamTrackKindVideo) {
384
+ [peerConnection removeVideoTrackAdapter:(RTCVideoTrack *)track];
385
+ }
386
+ }
387
+
388
+ // Clean up peerConnection's streams and tracks
389
+ [peerConnection.remoteStreams removeAllObjects];
390
+ [peerConnection.remoteTracks removeAllObjects];
391
+
392
+ // Clean up peerConnection's dataChannels.
393
+ NSMutableDictionary<NSString *, DataChannelWrapper *> *dataChannels = peerConnection.dataChannels;
394
+ for (NSString *tag in dataChannels) {
395
+ dataChannels[tag].delegate = nil;
396
+ // There is no need to close the RTCDataChannel because it is owned by the
397
+ // RTCPeerConnection and the latter will close the former.
398
+ }
399
+ [dataChannels removeAllObjects];
400
+
401
+ [self.peerConnections removeObjectForKey:objectID];
402
+ }
403
+
404
+ RCT_EXPORT_METHOD(peerConnectionGetStats
405
+ : (nonnull NSNumber *)objectID resolver
406
+ : (RCTPromiseResolveBlock)resolve rejecter
407
+ : (RCTPromiseRejectBlock)reject) {
408
+ RTCPeerConnection *peerConnection = self.peerConnections[objectID];
409
+ if (!peerConnection) {
410
+ RCTLogWarn(@"PeerConnection %@ not found in peerConnectionGetStats()", objectID);
411
+ resolve(@"[]");
412
+ return;
413
+ }
414
+
415
+ [peerConnection statisticsWithCompletionHandler:^(RTCStatisticsReport *report) {
416
+ resolve([self statsToJSON:report]);
417
+ }];
418
+ }
419
+
420
+ RCT_EXPORT_METHOD(receiverGetStats
421
+ : (nonnull NSNumber *)pcId receiverId
422
+ : (nonnull NSString *)receiverId resolver
423
+ : (RCTPromiseResolveBlock)resolve rejecter
424
+ : (RCTPromiseRejectBlock)reject) {
425
+ RTCPeerConnection *peerConnection = self.peerConnections[pcId];
426
+ if (!peerConnection) {
427
+ RCTLogWarn(@"PeerConnection %@ not found in receiverGetStats()", pcId);
428
+ resolve(@"[]");
429
+ return;
430
+ }
431
+
432
+ RTCRtpReceiver *receiver;
433
+ for (RTCRtpReceiver *findRecv in peerConnection.receivers) {
434
+ if ([findRecv.receiverId isEqualToString:receiverId]) {
435
+ receiver = findRecv;
436
+ break;
437
+ }
438
+ }
439
+
440
+ if (!receiver) {
441
+ RCTLogWarn(@"RTCRtpReceiver %@ not found in receiverGetStats()", receiverId);
442
+ resolve(@"[]");
443
+ return;
444
+ }
445
+
446
+ [peerConnection statisticsForReceiver:receiver
447
+ completionHandler:^(RTCStatisticsReport *report) {
448
+ resolve([self statsToJSON:report]);
449
+ }];
450
+ }
451
+
452
+ RCT_EXPORT_METHOD(senderGetStats
453
+ : (nonnull NSNumber *)pcId senderId
454
+ : (nonnull NSString *)senderId resolver
455
+ : (RCTPromiseResolveBlock)resolve rejecter
456
+ : (RCTPromiseRejectBlock)reject) {
457
+ RTCPeerConnection *peerConnection = self.peerConnections[pcId];
458
+ if (!peerConnection) {
459
+ RCTLogWarn(@"PeerConnection %@ not found in senderGetStats()", pcId);
460
+ resolve(@"[]");
461
+ return;
462
+ }
463
+
464
+ RTCRtpSender *sender;
465
+ for (RTCRtpSender *findSend in peerConnection.senders) {
466
+ if ([findSend.senderId isEqualToString:senderId]) {
467
+ sender = findSend;
468
+ break;
469
+ }
470
+ }
471
+
472
+ if (!sender) {
473
+ RCTLogWarn(@"RTCRtpSender %@ not found in senderGetStats()", senderId);
474
+ resolve(@"[]");
475
+ return;
476
+ }
477
+
478
+ [peerConnection statisticsForSender:sender
479
+ completionHandler:^(RTCStatisticsReport *report) {
480
+ resolve([self statsToJSON:report]);
481
+ }];
482
+ }
483
+
484
+ RCT_EXPORT_METHOD(peerConnectionRestartIce : (nonnull NSNumber *)objectID) {
485
+ RTCPeerConnection *peerConnection = self.peerConnections[objectID];
486
+ if (!peerConnection) {
487
+ return;
488
+ }
489
+
490
+ [peerConnection restartIce];
491
+ }
492
+
493
+ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(peerConnectionAddTrack
494
+ : (nonnull NSNumber *)objectID trackId
495
+ : (NSString *)trackId options
496
+ : (NSDictionary *)options) {
497
+ __block id params = nil;
498
+
499
+ dispatch_sync(self.workerQueue, ^{
500
+ RTCPeerConnection *peerConnection = self.peerConnections[objectID];
501
+ if (!peerConnection) {
502
+ RCTLogWarn(@"PeerConnection %@ not found in peerConnectionAddTrack()", objectID);
503
+ return;
504
+ }
505
+
506
+ RTCMediaStreamTrack *track = self.localTracks[trackId];
507
+
508
+ NSArray *streamIds = [options objectForKey:@"streamIds"];
509
+ RTCRtpSender *sender = [peerConnection addTrack:track streamIds:streamIds];
510
+ RTCRtpTransceiver *transceiver = nil;
511
+
512
+ for (RTCRtpTransceiver *t in peerConnection.transceivers) {
513
+ if ([t.sender.senderId isEqual:sender.senderId]) {
514
+ transceiver = t;
515
+ break;
516
+ }
517
+ }
518
+
519
+ if (!transceiver) {
520
+ RCTLogWarn(@"Transceiver not found in peerConnectionAddTrack()");
521
+ return;
522
+ }
523
+
524
+ params = @{
525
+ @"transceiverOrder" : [NSNumber numberWithInt:_transceiverNextId++],
526
+ @"transceiver" : [SerializeUtils transceiverToJSONWithPeerConnectionId:objectID transceiver:transceiver],
527
+ @"sender" : [SerializeUtils senderToJSONWithPeerConnectionId:objectID sender:sender]
528
+ };
529
+ });
530
+
531
+ return params;
532
+ }
533
+
534
+ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(peerConnectionAddTransceiver
535
+ : (nonnull NSNumber *)objectID options
536
+ : (NSDictionary *)options) {
537
+ __block id params = nil;
538
+
539
+ dispatch_sync(self.workerQueue, ^{
540
+ RTCPeerConnection *peerConnection = self.peerConnections[objectID];
541
+ if (!peerConnection) {
542
+ RCTLogWarn(@"PeerConnection %@ not found in peerConnectionAddTransceiver()", objectID);
543
+ return;
544
+ }
545
+
546
+ RTCRtpTransceiver *transceiver = nil;
547
+ NSString *kind = [options objectForKey:@"type"];
548
+ NSString *trackId = [options objectForKey:@"trackId"];
549
+ RTCRtpMediaType type = RTCRtpMediaTypeUnsupported;
550
+
551
+ if (kind) {
552
+ if ([kind isEqual:@"audio"]) {
553
+ type = RTCRtpMediaTypeAudio;
554
+ } else if ([kind isEqual:@"video"]) {
555
+ type = RTCRtpMediaTypeVideo;
556
+ }
557
+
558
+ NSDictionary *initOptions = [options objectForKey:@"init"];
559
+ RTCRtpTransceiverInit *transceiverInit = [SerializeUtils parseTransceiverOptions:initOptions];
560
+
561
+ transceiver = [peerConnection addTransceiverOfType:type init:transceiverInit];
562
+ } else if (trackId) {
563
+ RTCMediaStreamTrack *track = self.localTracks[trackId];
564
+
565
+ if (!track) {
566
+ track = peerConnection.remoteTracks[trackId];
567
+ }
568
+
569
+ NSDictionary *initOptions = [options objectForKey:@"init"];
570
+ RTCRtpTransceiverInit *transceiverInit = [SerializeUtils parseTransceiverOptions:initOptions];
571
+
572
+ transceiver = [peerConnection addTransceiverWithTrack:track init:transceiverInit];
573
+ } else {
574
+ RCTLogWarn(@"peerConnectionAddTransceiver() no type nor trackId provided in options");
575
+ return;
576
+ }
577
+
578
+ if (transceiver == nil) {
579
+ RCTLogWarn(@"peerConnectionAddTransceiver() Error adding transceiver");
580
+ return;
581
+ }
582
+
583
+ params = @{
584
+ @"transceiverOrder" : [NSNumber numberWithInt:_transceiverNextId++],
585
+ @"transceiver" : [SerializeUtils transceiverToJSONWithPeerConnectionId:objectID transceiver:transceiver]
586
+ };
587
+ });
588
+
589
+ return params;
590
+ }
591
+
592
+ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(peerConnectionRemoveTrack
593
+ : (nonnull NSNumber *)objectID senderId
594
+ : (nonnull NSString *)senderId) {
595
+ __block BOOL ret = NO;
596
+
597
+ dispatch_sync(self.workerQueue, ^{
598
+ RTCPeerConnection *peerConnection = self.peerConnections[objectID];
599
+ if (!peerConnection) {
600
+ RCTLogWarn(@"PeerConnection %@ not found in peerConnectionRemoveTrack()", objectID);
601
+ return;
602
+ }
603
+
604
+ RTCRtpSender *sender = nil;
605
+
606
+ for (RTCRtpSender *s in peerConnection.senders) {
607
+ if ([s.senderId isEqual:senderId]) {
608
+ sender = s;
609
+ break;
610
+ }
611
+ }
612
+
613
+ if (!sender) {
614
+ RCTLogWarn(@"Sender not found in peerConnectionRemoveTrack()");
615
+ return;
616
+ }
617
+
618
+ ret = [peerConnection removeTrack:sender];
619
+ });
620
+
621
+ return @(ret);
622
+ }
623
+
624
+ // TODO: move these below to some SerializeUtils file
625
+
626
+ /**
627
+ * Constructs a JSON <tt>NSString</tt> representation of a specific
628
+ * <tt>RTCStatisticsReport</tt>s.
629
+ * <p>
630
+ *
631
+ * @param <tt>RTCStatisticsReport</tt>s
632
+ * @return an <tt>NSString</tt> which represents the specified <tt>report</tt> in
633
+ * JSON format
634
+ */
635
+ - (NSString *)statsToJSON:(RTCStatisticsReport *)report {
636
+ /*
637
+ The initial capacity matters, of course, because it determines how many
638
+ times the NSMutableString will have grow. But walking through the reports
639
+ to compute an initial capacity which exactly matches the requirements of
640
+ the reports is too much work without real-world bang here. An improvement
641
+ should be caching the required capacity from the previous invocation of the
642
+ method and using it as the initial capacity in the next invocation.
643
+ As I didn't want to go even through that,choosing just about any initial
644
+ capacity is OK because NSMutableCopy doesn't have too bad a strategy of growing.
645
+ */
646
+ NSMutableString *s = [NSMutableString stringWithCapacity:16 * 1024];
647
+
648
+ [s appendString:@"["];
649
+ BOOL firstReport = YES;
650
+ for (NSString *key in report.statistics.allKeys) {
651
+ if (firstReport) {
652
+ firstReport = NO;
653
+ } else {
654
+ [s appendString:@","];
655
+ }
656
+
657
+ [s appendString:@"[\""];
658
+ [s appendString:key];
659
+ [s appendString:@"\",{"];
660
+
661
+ RTCStatistics *statistics = report.statistics[key];
662
+ [s appendString:@"\"timestamp\":"];
663
+ [s appendFormat:@"%f", statistics.timestamp_us / 1000.0];
664
+ [s appendString:@",\"type\":\""];
665
+ [s appendString:statistics.type];
666
+ [s appendString:@"\",\"id\":\""];
667
+ [s appendString:statistics.id];
668
+ [s appendString:@"\""];
669
+
670
+ for (id key in statistics.values) {
671
+ [s appendString:@","];
672
+ [s appendString:@"\""];
673
+ [s appendString:key];
674
+ [s appendString:@"\":"];
675
+ NSObject *statisticsValue = [statistics.values objectForKey:key];
676
+ [self appendValue:statisticsValue toString:s];
677
+ }
678
+
679
+ [s appendString:@"}]"];
680
+ }
681
+
682
+ [s appendString:@"]"];
683
+
684
+ return s;
685
+ }
686
+
687
+ - (void)appendValue:(NSObject *)statisticsValue toString:(NSMutableString *)s {
688
+ if ([statisticsValue isKindOfClass:[NSArray class]]) {
689
+ [s appendString:@"["];
690
+ BOOL firstValue = YES;
691
+ for (NSObject *element in (NSArray *)statisticsValue) {
692
+ if (firstValue) {
693
+ firstValue = NO;
694
+ } else {
695
+ [s appendString:@","];
696
+ }
697
+
698
+ [s appendString:@"\""];
699
+ [s appendString:[NSString stringWithFormat:@"%@", element]];
700
+ [s appendString:@"\""];
701
+ }
702
+
703
+ [s appendString:@"]"];
704
+ } else if ([statisticsValue isKindOfClass:[NSDictionary class]]) {
705
+ NSError *error;
706
+ NSData *jsonData = [NSJSONSerialization dataWithJSONObject:statisticsValue options:0 error:&error];
707
+
708
+ if (!jsonData) {
709
+ [s appendString:@"\""];
710
+ [s appendString:[NSString stringWithFormat:@"%@", statisticsValue]];
711
+ [s appendString:@"\""];
712
+ } else {
713
+ NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
714
+ [s appendString:jsonString];
715
+ }
716
+ } else if ([statisticsValue isKindOfClass:[NSNumber class]]) {
717
+ [s appendString:[NSString stringWithFormat:@"%@", statisticsValue]];
718
+ } else {
719
+ [s appendString:@"\""];
720
+ [s appendString:[NSString stringWithFormat:@"%@", statisticsValue]];
721
+ [s appendString:@"\""];
722
+ }
723
+ }
724
+
725
+ - (NSString *)stringForPeerConnectionState:(RTCPeerConnectionState)state {
726
+ switch (state) {
727
+ case RTCPeerConnectionStateNew:
728
+ return @"new";
729
+ case RTCPeerConnectionStateConnecting:
730
+ return @"connecting";
731
+ case RTCPeerConnectionStateConnected:
732
+ return @"connected";
733
+ case RTCPeerConnectionStateDisconnected:
734
+ return @"disconnected";
735
+ case RTCPeerConnectionStateFailed:
736
+ return @"failed";
737
+ case RTCPeerConnectionStateClosed:
738
+ return @"closed";
739
+ }
740
+ return nil;
741
+ }
742
+
743
+ - (NSString *)stringForICEConnectionState:(RTCIceConnectionState)state {
744
+ switch (state) {
745
+ case RTCIceConnectionStateNew:
746
+ return @"new";
747
+ case RTCIceConnectionStateChecking:
748
+ return @"checking";
749
+ case RTCIceConnectionStateConnected:
750
+ return @"connected";
751
+ case RTCIceConnectionStateCompleted:
752
+ return @"completed";
753
+ case RTCIceConnectionStateFailed:
754
+ return @"failed";
755
+ case RTCIceConnectionStateDisconnected:
756
+ return @"disconnected";
757
+ case RTCIceConnectionStateClosed:
758
+ return @"closed";
759
+ case RTCIceConnectionStateCount:
760
+ return @"count";
761
+ }
762
+ return nil;
763
+ }
764
+
765
+ - (NSString *)stringForICEGatheringState:(RTCIceGatheringState)state {
766
+ switch (state) {
767
+ case RTCIceGatheringStateNew:
768
+ return @"new";
769
+ case RTCIceGatheringStateGathering:
770
+ return @"gathering";
771
+ case RTCIceGatheringStateComplete:
772
+ return @"complete";
773
+ }
774
+ return nil;
775
+ }
776
+
777
+ - (NSString *)stringForSignalingState:(RTCSignalingState)state {
778
+ switch (state) {
779
+ case RTCSignalingStateStable:
780
+ return @"stable";
781
+ case RTCSignalingStateHaveLocalOffer:
782
+ return @"have-local-offer";
783
+ case RTCSignalingStateHaveLocalPrAnswer:
784
+ return @"have-local-pranswer";
785
+ case RTCSignalingStateHaveRemoteOffer:
786
+ return @"have-remote-offer";
787
+ case RTCSignalingStateHaveRemotePrAnswer:
788
+ return @"have-remote-pranswer";
789
+ case RTCSignalingStateClosed:
790
+ return @"closed";
791
+ }
792
+ return nil;
793
+ }
794
+
795
+ #pragma mark - RTCPeerConnectionDelegate methods
796
+
797
+ - (void)peerConnection:(RTCPeerConnection *)peerConnection didChangeSignalingState:(RTCSignalingState)newState {
798
+ dispatch_async(self.workerQueue, ^{
799
+ [self sendEventWithName:kEventPeerConnectionSignalingStateChanged
800
+ body:@{
801
+ @"pcId" : peerConnection.reactTag,
802
+ @"signalingState" : [self stringForSignalingState:newState]
803
+ }];
804
+ });
805
+ }
806
+
807
+ - (void)peerConnectionShouldNegotiate:(RTCPeerConnection *)peerConnection {
808
+ dispatch_async(self.workerQueue, ^{
809
+ [self sendEventWithName:kEventPeerConnectionOnRenegotiationNeeded body:@{@"pcId" : peerConnection.reactTag}];
810
+ });
811
+ }
812
+
813
+ - (void)peerConnection:(RTCPeerConnection *)peerConnection didChangeConnectionState:(RTCPeerConnectionState)newState {
814
+ dispatch_async(self.workerQueue, ^{
815
+ [self sendEventWithName:kEventPeerConnectionStateChanged
816
+ body:@{
817
+ @"pcId" : peerConnection.reactTag,
818
+ @"connectionState" : [self stringForPeerConnectionState:newState]
819
+ }];
820
+ });
821
+ }
822
+
823
+ - (void)peerConnection:(RTCPeerConnection *)peerConnection didChangeIceConnectionState:(RTCIceConnectionState)newState {
824
+ dispatch_async(self.workerQueue, ^{
825
+ [self sendEventWithName:kEventPeerConnectionIceConnectionChanged
826
+ body:@{
827
+ @"pcId" : peerConnection.reactTag,
828
+ @"iceConnectionState" : [self stringForICEConnectionState:newState]
829
+ }];
830
+ });
831
+ }
832
+
833
+ - (void)peerConnection:(RTCPeerConnection *)peerConnection didChangeIceGatheringState:(RTCIceGatheringState)newState {
834
+ dispatch_async(self.workerQueue, ^{
835
+ id newSdp = @{};
836
+ if (newState == RTCIceGatheringStateComplete) {
837
+ // Can happen when doing a rollback.
838
+ if (peerConnection.localDescription) {
839
+ newSdp = @{
840
+ @"type" : [RTCSessionDescription stringForType:peerConnection.localDescription.type],
841
+ @"sdp" : peerConnection.localDescription.sdp
842
+ };
843
+ }
844
+ }
845
+
846
+ [self sendEventWithName:kEventPeerConnectionIceGatheringChanged
847
+ body:@{
848
+ @"pcId" : peerConnection.reactTag,
849
+ @"iceGatheringState" : [self stringForICEGatheringState:newState],
850
+ @"sdp" : newSdp
851
+ }];
852
+ });
853
+ }
854
+
855
+ - (void)peerConnection:(RTCPeerConnection *)peerConnection didGenerateIceCandidate:(RTCIceCandidate *)candidate {
856
+ dispatch_async(self.workerQueue, ^{
857
+ id newSdp = @{};
858
+ // Can happen when doing a rollback.
859
+ if (peerConnection.localDescription) {
860
+ newSdp = @{
861
+ @"type" : [RTCSessionDescription stringForType:peerConnection.localDescription.type],
862
+ @"sdp" : peerConnection.localDescription.sdp
863
+ };
864
+ }
865
+
866
+ [self sendEventWithName:kEventPeerConnectionGotICECandidate
867
+ body:@{
868
+ @"pcId" : peerConnection.reactTag,
869
+ @"candidate" : @{
870
+ @"candidate" : candidate.sdp,
871
+ @"sdpMLineIndex" : @(candidate.sdpMLineIndex),
872
+ @"sdpMid" : candidate.sdpMid
873
+ },
874
+ @"sdp" : newSdp
875
+ }];
876
+ });
877
+ }
878
+
879
+ - (void)peerConnection:(RTCPeerConnection *)peerConnection didOpenDataChannel:(RTCDataChannel *)dataChannel {
880
+ dispatch_async(self.workerQueue, ^{
881
+ NSString *reactTag = [[NSUUID UUID] UUIDString];
882
+ DataChannelWrapper *dcw = [[DataChannelWrapper alloc] initWithChannel:dataChannel reactTag:reactTag];
883
+ dcw.pcId = peerConnection.reactTag;
884
+ peerConnection.dataChannels[reactTag] = dcw;
885
+ dcw.delegate = self;
886
+
887
+ NSDictionary *dataChannelInfo = @{
888
+ @"peerConnectionId" : peerConnection.reactTag,
889
+ @"reactTag" : reactTag,
890
+ @"label" : dataChannel.label,
891
+ @"id" : @(dataChannel.channelId),
892
+ @"ordered" : @(dataChannel.isOrdered),
893
+ @"maxPacketLifeTime" : @(dataChannel.maxPacketLifeTime),
894
+ @"maxRetransmits" : @(dataChannel.maxRetransmits),
895
+ @"protocol" : dataChannel.protocol,
896
+ @"negotiated" : @(dataChannel.isNegotiated),
897
+ @"readyState" : [self stringForDataChannelState:dataChannel.readyState]
898
+ };
899
+ NSDictionary *body = @{@"pcId" : peerConnection.reactTag, @"dataChannel" : dataChannelInfo};
900
+
901
+ [self sendEventWithName:kEventPeerConnectionDidOpenDataChannel body:body];
902
+ });
903
+ }
904
+
905
+ - (void)peerConnection:(RTC_OBJC_TYPE(RTCPeerConnection) *)peerConnection
906
+ didAddReceiver:(RTC_OBJC_TYPE(RTCRtpReceiver) *)rtpReceiver
907
+ streams:(NSArray<RTC_OBJC_TYPE(RTCMediaStream) *> *)mediaStreams {
908
+ dispatch_async(self.workerQueue, ^{
909
+ RTCRtpTransceiver *transceiver = nil;
910
+ for (RTCRtpTransceiver *t in peerConnection.transceivers) {
911
+ if ([rtpReceiver.receiverId isEqual:t.receiver.receiverId]) {
912
+ transceiver = t;
913
+ break;
914
+ }
915
+ }
916
+
917
+ if (!transceiver) {
918
+ RCTLogWarn(@"Transceiver not found in didAddReceiver()");
919
+ return;
920
+ }
921
+
922
+ RTCMediaStreamTrack *track = rtpReceiver.track;
923
+
924
+ // We need to fire this event for an existing track sometimes, like
925
+ // when the transceiver direction (on the sending side) switches from
926
+ // sendrecv to recvonly and then back.
927
+ BOOL existingTrack = peerConnection.remoteTracks[track.trackId] != nil;
928
+
929
+ if (!existingTrack) {
930
+ if (track.kind == kRTCMediaStreamTrackKindVideo) {
931
+ RTCVideoTrack *videoTrack = (RTCVideoTrack *)track;
932
+ [peerConnection addVideoTrackAdapter:videoTrack];
933
+ } else if (track.kind == kRTCMediaStreamTrackKindAudio) {
934
+ RTCAudioTrack *audioTrack = (RTCAudioTrack *)track;
935
+ WebRTCModuleOptions *options = [WebRTCModuleOptions sharedInstance];
936
+ audioTrack.source.volume = options.defaultTrackVolume;
937
+ }
938
+
939
+ peerConnection.remoteTracks[track.trackId] = track;
940
+ }
941
+
942
+ NSMutableDictionary *params = [NSMutableDictionary new];
943
+ NSMutableArray *streams = [NSMutableArray new];
944
+
945
+ for (RTCMediaStream *stream in mediaStreams) {
946
+ NSString *streamReactTag = nil;
947
+
948
+ for (NSString *key in [peerConnection.remoteStreams allKeys]) {
949
+ if ([[peerConnection.remoteStreams objectForKey:key].streamId isEqual:stream.streamId]) {
950
+ streamReactTag = key;
951
+ break;
952
+ }
953
+ }
954
+
955
+ if (!streamReactTag) {
956
+ streamReactTag = [[NSUUID UUID] UUIDString];
957
+ }
958
+
959
+ // Make sure the stored stream is updated in case we get a new reference.
960
+ peerConnection.remoteStreams[streamReactTag] = stream;
961
+
962
+ [streams addObject:[SerializeUtils streamToJSONWithPeerConnectionId:peerConnection.reactTag
963
+ stream:stream
964
+ streamReactTag:streamReactTag]];
965
+ }
966
+
967
+ params[@"streams"] = streams;
968
+ params[@"receiver"] = [SerializeUtils receiverToJSONWithPeerConnectionId:peerConnection.reactTag
969
+ receiver:rtpReceiver];
970
+ params[@"transceiverOrder"] = [NSNumber numberWithInt:_transceiverNextId++];
971
+ params[@"transceiver"] = [SerializeUtils transceiverToJSONWithPeerConnectionId:peerConnection.reactTag
972
+ transceiver:transceiver];
973
+ params[@"pcId"] = peerConnection.reactTag;
974
+
975
+ [self sendEventWithName:kEventPeerConnectionOnTrack body:params];
976
+ });
977
+ }
978
+
979
+ - (void)peerConnection:(RTC_OBJC_TYPE(RTCPeerConnection) *)peerConnection
980
+ didRemoveReceiver:(RTC_OBJC_TYPE(RTCRtpReceiver) *)rtpReceiver {
981
+ dispatch_async(self.workerQueue, ^{
982
+ NSMutableDictionary *params = [NSMutableDictionary new];
983
+
984
+ params[@"pcId"] = peerConnection.reactTag;
985
+ params[@"receiverId"] = rtpReceiver.receiverId;
986
+
987
+ [self sendEventWithName:kEventPeerConnectionOnRemoveTrack body:params];
988
+ });
989
+ }
990
+
991
+ - (void)peerConnection:(nonnull RTCPeerConnection *)peerConnection
992
+ didRemoveIceCandidates:(nonnull NSArray<RTCIceCandidate *> *)candidates {
993
+ // Unimplemented, there is no matching web API.
994
+ }
995
+
996
+ - (void)peerConnection:(nonnull RTCPeerConnection *)peerConnection didAddStream:(nonnull RTCMediaStream *)stream {
997
+ // Unused in Unified Plan.
998
+ }
999
+
1000
+ - (void)peerConnection:(nonnull RTCPeerConnection *)peerConnection didRemoveStream:(nonnull RTCMediaStream *)stream {
1001
+ // Unused in Unified Plan.
1002
+ }
1003
+
1004
+ @end