@sbhjt-gr/react-native-webrtc 124.0.0
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.
- package/.clang-format +11 -0
- package/.claude/settings.local.json +9 -0
- package/.eslintignore +6 -0
- package/.nvmrc +1 -0
- package/ISSUE_TEMPLATE.md +40 -0
- package/LICENSE +22 -0
- package/README.md +103 -0
- package/android/build.gradle +37 -0
- package/android/consumer-rules.pro +3 -0
- package/android/src/main/AndroidManifest.xml +11 -0
- package/android/src/main/java/com/oney/WebRTCModule/AbstractVideoCaptureController.java +113 -0
- package/android/src/main/java/com/oney/WebRTCModule/CameraCaptureController.java +338 -0
- package/android/src/main/java/com/oney/WebRTCModule/CameraEventsHandler.java +49 -0
- package/android/src/main/java/com/oney/WebRTCModule/DataChannelWrapper.java +99 -0
- package/android/src/main/java/com/oney/WebRTCModule/DataPacketCryptorManager.java +63 -0
- package/android/src/main/java/com/oney/WebRTCModule/DisplayUtils.java +16 -0
- package/android/src/main/java/com/oney/WebRTCModule/EglUtils.java +66 -0
- package/android/src/main/java/com/oney/WebRTCModule/GetUserMediaImpl.java +539 -0
- package/android/src/main/java/com/oney/WebRTCModule/LibraryLoader.java +21 -0
- package/android/src/main/java/com/oney/WebRTCModule/MediaProjectionNotification.java +70 -0
- package/android/src/main/java/com/oney/WebRTCModule/MediaProjectionService.java +82 -0
- package/android/src/main/java/com/oney/WebRTCModule/PeerConnectionObserver.java +588 -0
- package/android/src/main/java/com/oney/WebRTCModule/RTCCryptoManager.java +493 -0
- package/android/src/main/java/com/oney/WebRTCModule/RTCVideoViewManager.java +98 -0
- package/android/src/main/java/com/oney/WebRTCModule/ReactBridgeUtil.java +36 -0
- package/android/src/main/java/com/oney/WebRTCModule/ScreenCaptureController.java +94 -0
- package/android/src/main/java/com/oney/WebRTCModule/SerializeUtils.java +342 -0
- package/android/src/main/java/com/oney/WebRTCModule/StringUtils.java +101 -0
- package/android/src/main/java/com/oney/WebRTCModule/ThreadUtils.java +41 -0
- package/android/src/main/java/com/oney/WebRTCModule/TrackCapturerEventsEmitter.java +34 -0
- package/android/src/main/java/com/oney/WebRTCModule/VideoTrackAdapter.java +137 -0
- package/android/src/main/java/com/oney/WebRTCModule/WebRTCModule.java +1643 -0
- package/android/src/main/java/com/oney/WebRTCModule/WebRTCModuleOptions.java +33 -0
- package/android/src/main/java/com/oney/WebRTCModule/WebRTCModulePackage.java +21 -0
- package/android/src/main/java/com/oney/WebRTCModule/WebRTCView.java +583 -0
- package/android/src/main/java/com/oney/WebRTCModule/palabra/PalabraClient.java +464 -0
- package/android/src/main/java/com/oney/WebRTCModule/palabra/PalabraConfig.java +17 -0
- package/android/src/main/java/com/oney/WebRTCModule/palabra/PalabraListener.java +7 -0
- package/android/src/main/java/com/oney/WebRTCModule/videoEffects/ProcessorProvider.java +38 -0
- package/android/src/main/java/com/oney/WebRTCModule/videoEffects/VideoEffectProcessor.java +59 -0
- package/android/src/main/java/com/oney/WebRTCModule/videoEffects/VideoFrameProcessor.java +19 -0
- package/android/src/main/java/com/oney/WebRTCModule/videoEffects/VideoFrameProcessorFactoryInterface.java +12 -0
- package/android/src/main/java/com/oney/WebRTCModule/webrtcutils/H264AndSoftwareVideoDecoderFactory.java +73 -0
- package/android/src/main/java/com/oney/WebRTCModule/webrtcutils/H264AndSoftwareVideoEncoderFactory.java +73 -0
- package/android/src/main/java/com/oney/WebRTCModule/webrtcutils/SoftwareVideoDecoderFactoryProxy.java +36 -0
- package/android/src/main/java/com/oney/WebRTCModule/webrtcutils/SoftwareVideoEncoderFactoryProxy.java +36 -0
- package/android/src/main/java/org/webrtc/Camera1Helper.java +54 -0
- package/android/src/main/java/org/webrtc/Camera2Helper.java +52 -0
- package/android/src/main/res/values/strings.xml +5 -0
- package/android/src/main/res/values/styles.xml +8 -0
- package/apple/.placeholder +0 -0
- package/ios/RCTWebRTC/CaptureController.h +18 -0
- package/ios/RCTWebRTC/CaptureController.m +29 -0
- package/ios/RCTWebRTC/CapturerEventsDelegate.h +12 -0
- package/ios/RCTWebRTC/DataChannelWrapper.h +27 -0
- package/ios/RCTWebRTC/DataChannelWrapper.m +42 -0
- package/ios/RCTWebRTC/I420Converter.h +22 -0
- package/ios/RCTWebRTC/I420Converter.m +164 -0
- package/ios/RCTWebRTC/PIPController.h +24 -0
- package/ios/RCTWebRTC/PIPController.m +234 -0
- package/ios/RCTWebRTC/PalabraAudioSink.h +13 -0
- package/ios/RCTWebRTC/PalabraAudioSink.m +18 -0
- package/ios/RCTWebRTC/PalabraClient.h +36 -0
- package/ios/RCTWebRTC/PalabraClient.m +584 -0
- package/ios/RCTWebRTC/RCTConvert+WebRTC.h +16 -0
- package/ios/RCTWebRTC/RCTConvert+WebRTC.m +206 -0
- package/ios/RCTWebRTC/RTCMediaStreamTrack+React.h +10 -0
- package/ios/RCTWebRTC/RTCMediaStreamTrack+React.m +16 -0
- package/ios/RCTWebRTC/RTCVideoViewManager.h +29 -0
- package/ios/RCTWebRTC/RTCVideoViewManager.m +411 -0
- package/ios/RCTWebRTC/SampleBufferVideoCallView.h +12 -0
- package/ios/RCTWebRTC/SampleBufferVideoCallView.m +178 -0
- package/ios/RCTWebRTC/ScreenCaptureController.h +20 -0
- package/ios/RCTWebRTC/ScreenCaptureController.m +83 -0
- package/ios/RCTWebRTC/ScreenCapturePickerViewManager.h +7 -0
- package/ios/RCTWebRTC/ScreenCapturePickerViewManager.m +60 -0
- package/ios/RCTWebRTC/ScreenCapturer.h +19 -0
- package/ios/RCTWebRTC/ScreenCapturer.m +264 -0
- package/ios/RCTWebRTC/SerializeUtils.h +28 -0
- package/ios/RCTWebRTC/SerializeUtils.m +314 -0
- package/ios/RCTWebRTC/SocketConnection.h +13 -0
- package/ios/RCTWebRTC/SocketConnection.m +137 -0
- package/ios/RCTWebRTC/TrackCapturerEventsEmitter.h +14 -0
- package/ios/RCTWebRTC/TrackCapturerEventsEmitter.m +37 -0
- package/ios/RCTWebRTC/VideoCaptureController.h +21 -0
- package/ios/RCTWebRTC/VideoCaptureController.m +328 -0
- package/ios/RCTWebRTC/WebRTCModule+Palabra.h +4 -0
- package/ios/RCTWebRTC/WebRTCModule+Palabra.m +83 -0
- package/ios/RCTWebRTC/WebRTCModule+Permissions.m +75 -0
- package/ios/RCTWebRTC/WebRTCModule+RTCAudioSession.m +20 -0
- package/ios/RCTWebRTC/WebRTCModule+RTCDataChannel.h +14 -0
- package/ios/RCTWebRTC/WebRTCModule+RTCDataChannel.m +165 -0
- package/ios/RCTWebRTC/WebRTCModule+RTCFrameCryptor.m +611 -0
- package/ios/RCTWebRTC/WebRTCModule+RTCMediaStream.h +14 -0
- package/ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m +533 -0
- package/ios/RCTWebRTC/WebRTCModule+RTCPeerConnection.h +24 -0
- package/ios/RCTWebRTC/WebRTCModule+RTCPeerConnection.m +1004 -0
- package/ios/RCTWebRTC/WebRTCModule+Transceivers.m +267 -0
- package/ios/RCTWebRTC/WebRTCModule+VideoTrackAdapter.h +12 -0
- package/ios/RCTWebRTC/WebRTCModule+VideoTrackAdapter.m +166 -0
- package/ios/RCTWebRTC/WebRTCModule.h +51 -0
- package/ios/RCTWebRTC/WebRTCModule.m +151 -0
- package/ios/RCTWebRTC/WebRTCModuleOptions.h +24 -0
- package/ios/RCTWebRTC/WebRTCModuleOptions.m +31 -0
- package/ios/RCTWebRTC/videoEffects/ProcessorProvider.h +9 -0
- package/ios/RCTWebRTC/videoEffects/ProcessorProvider.m +23 -0
- package/ios/RCTWebRTC/videoEffects/VideoEffectProcessor.h +13 -0
- package/ios/RCTWebRTC/videoEffects/VideoEffectProcessor.m +23 -0
- package/ios/RCTWebRTC/videoEffects/VideoFrameProcessor.h +8 -0
- package/ios/RCTWebRTC.xcodeproj/project.pbxproj +404 -0
- package/ios/RCTWebRTC.xcworkspace/contents.xcworkspacedata +10 -0
- package/lib/commonjs/Constraints.js +2 -0
- package/lib/commonjs/Constraints.js.map +1 -0
- package/lib/commonjs/EventEmitter.js +51 -0
- package/lib/commonjs/EventEmitter.js.map +1 -0
- package/lib/commonjs/Logger.js +47 -0
- package/lib/commonjs/Logger.js.map +1 -0
- package/lib/commonjs/MediaDevices.js +54 -0
- package/lib/commonjs/MediaDevices.js.map +1 -0
- package/lib/commonjs/MediaStream.js +137 -0
- package/lib/commonjs/MediaStream.js.map +1 -0
- package/lib/commonjs/MediaStreamError.js +19 -0
- package/lib/commonjs/MediaStreamError.js.map +1 -0
- package/lib/commonjs/MediaStreamErrorEvent.js +17 -0
- package/lib/commonjs/MediaStreamErrorEvent.js.map +1 -0
- package/lib/commonjs/MediaStreamTrack.js +203 -0
- package/lib/commonjs/MediaStreamTrack.js.map +1 -0
- package/lib/commonjs/MediaStreamTrackEvent.js +26 -0
- package/lib/commonjs/MediaStreamTrackEvent.js.map +1 -0
- package/lib/commonjs/MessageEvent.js +27 -0
- package/lib/commonjs/MessageEvent.js.map +1 -0
- package/lib/commonjs/Permissions.js +116 -0
- package/lib/commonjs/Permissions.js.map +1 -0
- package/lib/commonjs/RTCAudioSession.js +33 -0
- package/lib/commonjs/RTCAudioSession.js.map +1 -0
- package/lib/commonjs/RTCDataChannel.js +165 -0
- package/lib/commonjs/RTCDataChannel.js.map +1 -0
- package/lib/commonjs/RTCDataChannelEvent.js +26 -0
- package/lib/commonjs/RTCDataChannelEvent.js.map +1 -0
- package/lib/commonjs/RTCDataPacketCryptor.js +76 -0
- package/lib/commonjs/RTCDataPacketCryptor.js.map +1 -0
- package/lib/commonjs/RTCDataPacketCryptorFactory.js +27 -0
- package/lib/commonjs/RTCDataPacketCryptorFactory.js.map +1 -0
- package/lib/commonjs/RTCErrorEvent.js +23 -0
- package/lib/commonjs/RTCErrorEvent.js.map +1 -0
- package/lib/commonjs/RTCFrameCryptor.js +138 -0
- package/lib/commonjs/RTCFrameCryptor.js.map +1 -0
- package/lib/commonjs/RTCFrameCryptorFactory.js +81 -0
- package/lib/commonjs/RTCFrameCryptorFactory.js.map +1 -0
- package/lib/commonjs/RTCIceCandidate.js +34 -0
- package/lib/commonjs/RTCIceCandidate.js.map +1 -0
- package/lib/commonjs/RTCIceCandidateEvent.js +28 -0
- package/lib/commonjs/RTCIceCandidateEvent.js.map +1 -0
- package/lib/commonjs/RTCKeyProvider.js +111 -0
- package/lib/commonjs/RTCKeyProvider.js.map +1 -0
- package/lib/commonjs/RTCPIPView.js +38 -0
- package/lib/commonjs/RTCPIPView.js.map +1 -0
- package/lib/commonjs/RTCPIPView.web.js +23 -0
- package/lib/commonjs/RTCPIPView.web.js.map +1 -0
- package/lib/commonjs/RTCPeerConnection.js +694 -0
- package/lib/commonjs/RTCPeerConnection.js.map +1 -0
- package/lib/commonjs/RTCRtcpParameters.js +24 -0
- package/lib/commonjs/RTCRtcpParameters.js.map +1 -0
- package/lib/commonjs/RTCRtpCapabilities.js +22 -0
- package/lib/commonjs/RTCRtpCapabilities.js.map +1 -0
- package/lib/commonjs/RTCRtpCodecCapability.js +19 -0
- package/lib/commonjs/RTCRtpCodecCapability.js.map +1 -0
- package/lib/commonjs/RTCRtpCodecParameters.js +38 -0
- package/lib/commonjs/RTCRtpCodecParameters.js.map +1 -0
- package/lib/commonjs/RTCRtpEncodingParameters.js +78 -0
- package/lib/commonjs/RTCRtpEncodingParameters.js.map +1 -0
- package/lib/commonjs/RTCRtpHeaderExtension.js +27 -0
- package/lib/commonjs/RTCRtpHeaderExtension.js.map +1 -0
- package/lib/commonjs/RTCRtpParameters.js +35 -0
- package/lib/commonjs/RTCRtpParameters.js.map +1 -0
- package/lib/commonjs/RTCRtpReceiveParameters.js +15 -0
- package/lib/commonjs/RTCRtpReceiveParameters.js.map +1 -0
- package/lib/commonjs/RTCRtpReceiver.js +53 -0
- package/lib/commonjs/RTCRtpReceiver.js.map +1 -0
- package/lib/commonjs/RTCRtpSendParameters.js +49 -0
- package/lib/commonjs/RTCRtpSendParameters.js.map +1 -0
- package/lib/commonjs/RTCRtpSender.js +67 -0
- package/lib/commonjs/RTCRtpSender.js.map +1 -0
- package/lib/commonjs/RTCRtpTransceiver.js +81 -0
- package/lib/commonjs/RTCRtpTransceiver.js.map +1 -0
- package/lib/commonjs/RTCSessionDescription.js +33 -0
- package/lib/commonjs/RTCSessionDescription.js.map +1 -0
- package/lib/commonjs/RTCTrackEvent.js +38 -0
- package/lib/commonjs/RTCTrackEvent.js.map +1 -0
- package/lib/commonjs/RTCUtil.js +186 -0
- package/lib/commonjs/RTCUtil.js.map +1 -0
- package/lib/commonjs/RTCView.js +16 -0
- package/lib/commonjs/RTCView.js.map +1 -0
- package/lib/commonjs/RTCView.web.js +62 -0
- package/lib/commonjs/RTCView.web.js.map +1 -0
- package/lib/commonjs/ScreenCapturePickerView.js +10 -0
- package/lib/commonjs/ScreenCapturePickerView.js.map +1 -0
- package/lib/commonjs/ScreenCapturePickerView.web.js +10 -0
- package/lib/commonjs/ScreenCapturePickerView.web.js.map +1 -0
- package/lib/commonjs/getDisplayMedia.js +33 -0
- package/lib/commonjs/getDisplayMedia.js.map +1 -0
- package/lib/commonjs/getUserMedia.js +101 -0
- package/lib/commonjs/getUserMedia.js.map +1 -0
- package/lib/commonjs/index.js +224 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/index.web.js +175 -0
- package/lib/commonjs/index.web.js.map +1 -0
- package/lib/commonjs/webStream.js +35 -0
- package/lib/commonjs/webStream.js.map +1 -0
- package/lib/module/Constraints.js +2 -0
- package/lib/module/Constraints.js.map +1 -0
- package/lib/module/EventEmitter.js +41 -0
- package/lib/module/EventEmitter.js.map +1 -0
- package/lib/module/Logger.js +39 -0
- package/lib/module/Logger.js.map +1 -0
- package/lib/module/MediaDevices.js +46 -0
- package/lib/module/MediaDevices.js.map +1 -0
- package/lib/module/MediaStream.js +129 -0
- package/lib/module/MediaStream.js.map +1 -0
- package/lib/module/MediaStreamError.js +12 -0
- package/lib/module/MediaStreamError.js.map +1 -0
- package/lib/module/MediaStreamErrorEvent.js +10 -0
- package/lib/module/MediaStreamErrorEvent.js.map +1 -0
- package/lib/module/MediaStreamTrack.js +195 -0
- package/lib/module/MediaStreamTrack.js.map +1 -0
- package/lib/module/MediaStreamTrackEvent.js +19 -0
- package/lib/module/MediaStreamTrackEvent.js.map +1 -0
- package/lib/module/MessageEvent.js +20 -0
- package/lib/module/MessageEvent.js.map +1 -0
- package/lib/module/Permissions.js +109 -0
- package/lib/module/Permissions.js.map +1 -0
- package/lib/module/RTCAudioSession.js +26 -0
- package/lib/module/RTCAudioSession.js.map +1 -0
- package/lib/module/RTCDataChannel.js +155 -0
- package/lib/module/RTCDataChannel.js.map +1 -0
- package/lib/module/RTCDataChannelEvent.js +19 -0
- package/lib/module/RTCDataChannelEvent.js.map +1 -0
- package/lib/module/RTCDataPacketCryptor.js +66 -0
- package/lib/module/RTCDataPacketCryptor.js.map +1 -0
- package/lib/module/RTCDataPacketCryptorFactory.js +19 -0
- package/lib/module/RTCDataPacketCryptorFactory.js.map +1 -0
- package/lib/module/RTCErrorEvent.js +16 -0
- package/lib/module/RTCErrorEvent.js.map +1 -0
- package/lib/module/RTCFrameCryptor.js +128 -0
- package/lib/module/RTCFrameCryptor.js.map +1 -0
- package/lib/module/RTCFrameCryptorFactory.js +70 -0
- package/lib/module/RTCFrameCryptorFactory.js.map +1 -0
- package/lib/module/RTCIceCandidate.js +27 -0
- package/lib/module/RTCIceCandidate.js.map +1 -0
- package/lib/module/RTCIceCandidateEvent.js +21 -0
- package/lib/module/RTCIceCandidateEvent.js.map +1 -0
- package/lib/module/RTCKeyProvider.js +101 -0
- package/lib/module/RTCKeyProvider.js.map +1 -0
- package/lib/module/RTCPIPView.js +26 -0
- package/lib/module/RTCPIPView.js.map +1 -0
- package/lib/module/RTCPIPView.web.js +11 -0
- package/lib/module/RTCPIPView.web.js.map +1 -0
- package/lib/module/RTCPeerConnection.js +684 -0
- package/lib/module/RTCPeerConnection.js.map +1 -0
- package/lib/module/RTCRtcpParameters.js +17 -0
- package/lib/module/RTCRtcpParameters.js.map +1 -0
- package/lib/module/RTCRtpCapabilities.js +15 -0
- package/lib/module/RTCRtpCapabilities.js.map +1 -0
- package/lib/module/RTCRtpCodecCapability.js +12 -0
- package/lib/module/RTCRtpCodecCapability.js.map +1 -0
- package/lib/module/RTCRtpCodecParameters.js +31 -0
- package/lib/module/RTCRtpCodecParameters.js.map +1 -0
- package/lib/module/RTCRtpEncodingParameters.js +71 -0
- package/lib/module/RTCRtpEncodingParameters.js.map +1 -0
- package/lib/module/RTCRtpHeaderExtension.js +20 -0
- package/lib/module/RTCRtpHeaderExtension.js.map +1 -0
- package/lib/module/RTCRtpParameters.js +27 -0
- package/lib/module/RTCRtpParameters.js.map +1 -0
- package/lib/module/RTCRtpReceiveParameters.js +7 -0
- package/lib/module/RTCRtpReceiveParameters.js.map +1 -0
- package/lib/module/RTCRtpReceiver.js +45 -0
- package/lib/module/RTCRtpReceiver.js.map +1 -0
- package/lib/module/RTCRtpSendParameters.js +41 -0
- package/lib/module/RTCRtpSendParameters.js.map +1 -0
- package/lib/module/RTCRtpSender.js +59 -0
- package/lib/module/RTCRtpSender.js.map +1 -0
- package/lib/module/RTCRtpTransceiver.js +74 -0
- package/lib/module/RTCRtpTransceiver.js.map +1 -0
- package/lib/module/RTCSessionDescription.js +26 -0
- package/lib/module/RTCSessionDescription.js.map +1 -0
- package/lib/module/RTCTrackEvent.js +31 -0
- package/lib/module/RTCTrackEvent.js.map +1 -0
- package/lib/module/RTCUtil.js +176 -0
- package/lib/module/RTCUtil.js.map +1 -0
- package/lib/module/RTCView.js +11 -0
- package/lib/module/RTCView.js.map +1 -0
- package/lib/module/RTCView.web.js +54 -0
- package/lib/module/RTCView.web.js.map +1 -0
- package/lib/module/ScreenCapturePickerView.js +3 -0
- package/lib/module/ScreenCapturePickerView.js.map +1 -0
- package/lib/module/ScreenCapturePickerView.web.js +4 -0
- package/lib/module/ScreenCapturePickerView.web.js.map +1 -0
- package/lib/module/getDisplayMedia.js +26 -0
- package/lib/module/getDisplayMedia.js.map +1 -0
- package/lib/module/getUserMedia.js +92 -0
- package/lib/module/getUserMedia.js.map +1 -0
- package/lib/module/index.js +60 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/index.web.js +114 -0
- package/lib/module/index.web.js.map +1 -0
- package/lib/module/webStream.js +27 -0
- package/lib/module/webStream.js.map +1 -0
- package/lib/typescript/Constraints.d.ts +19 -0
- package/lib/typescript/EventEmitter.d.ts +6 -0
- package/lib/typescript/Logger.d.ts +13 -0
- package/lib/typescript/MediaDevices.d.ts +30 -0
- package/lib/typescript/MediaStream.d.ts +48 -0
- package/lib/typescript/MediaStreamError.d.ts +6 -0
- package/lib/typescript/MediaStreamErrorEvent.d.ts +6 -0
- package/lib/typescript/MediaStreamTrack.d.ts +101 -0
- package/lib/typescript/MediaStreamTrackEvent.d.ts +19 -0
- package/lib/typescript/MessageEvent.d.ts +20 -0
- package/lib/typescript/Permissions.d.ts +55 -0
- package/lib/typescript/RTCAudioSession.d.ts +10 -0
- package/lib/typescript/RTCDataChannel.d.ts +43 -0
- package/lib/typescript/RTCDataChannelEvent.d.ts +19 -0
- package/lib/typescript/RTCDataPacketCryptor.d.ts +12 -0
- package/lib/typescript/RTCDataPacketCryptorFactory.d.ts +6 -0
- package/lib/typescript/RTCErrorEvent.d.ts +12 -0
- package/lib/typescript/RTCFrameCryptor.d.ts +47 -0
- package/lib/typescript/RTCFrameCryptorFactory.d.ts +21 -0
- package/lib/typescript/RTCIceCandidate.d.ts +17 -0
- package/lib/typescript/RTCIceCandidateEvent.d.ts +20 -0
- package/lib/typescript/RTCKeyProvider.d.ts +21 -0
- package/lib/typescript/RTCPIPView.d.ts +15 -0
- package/lib/typescript/RTCPIPView.web.d.ts +13 -0
- package/lib/typescript/RTCPeerConnection.d.ts +117 -0
- package/lib/typescript/RTCRtcpParameters.d.ts +10 -0
- package/lib/typescript/RTCRtpCapabilities.d.ts +9 -0
- package/lib/typescript/RTCRtpCodecCapability.d.ts +7 -0
- package/lib/typescript/RTCRtpCodecParameters.d.ts +16 -0
- package/lib/typescript/RTCRtpEncodingParameters.d.ts +23 -0
- package/lib/typescript/RTCRtpHeaderExtension.d.ts +12 -0
- package/lib/typescript/RTCRtpParameters.d.ts +19 -0
- package/lib/typescript/RTCRtpReceiveParameters.d.ts +4 -0
- package/lib/typescript/RTCRtpReceiver.d.ts +21 -0
- package/lib/typescript/RTCRtpSendParameters.d.ts +20 -0
- package/lib/typescript/RTCRtpSender.d.ts +22 -0
- package/lib/typescript/RTCRtpTransceiver.d.ts +31 -0
- package/lib/typescript/RTCSessionDescription.d.ts +12 -0
- package/lib/typescript/RTCTrackEvent.d.ts +29 -0
- package/lib/typescript/RTCUtil.d.ts +37 -0
- package/lib/typescript/RTCView.d.ts +117 -0
- package/lib/typescript/RTCView.web.d.ts +25 -0
- package/lib/typescript/ScreenCapturePickerView.d.ts +2 -0
- package/lib/typescript/ScreenCapturePickerView.web.d.ts +1 -0
- package/lib/typescript/getDisplayMedia.d.ts +2 -0
- package/lib/typescript/getUserMedia.d.ts +7 -0
- package/lib/typescript/index.d.ts +22 -0
- package/lib/typescript/index.web.d.ts +101 -0
- package/lib/typescript/webStream.d.ts +3 -0
- package/livekit-react-native-webrtc.podspec +29 -0
- package/macos/RCTWebRTC.xcodeproj/project.pbxproj +324 -0
- package/macos/RCTWebRTC.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- package/macos/RCTWebRTC.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/metro.config.js +7 -0
- package/metro.config.macos.js +14 -0
- package/package.json +66 -0
- package/react-native.config.js +11 -0
- package/src/.eslintrc.cjs +67 -0
- package/src/Constraints.ts +21 -0
- package/src/EventEmitter.ts +65 -0
- package/src/Logger.ts +49 -0
- package/src/MediaDevices.ts +53 -0
- package/src/MediaStream.ts +161 -0
- package/src/MediaStreamError.ts +12 -0
- package/src/MediaStreamErrorEvent.ts +11 -0
- package/src/MediaStreamTrack.ts +284 -0
- package/src/MediaStreamTrackEvent.ts +25 -0
- package/src/MessageEvent.ts +26 -0
- package/src/Permissions.ts +133 -0
- package/src/RTCAudioSession.ts +25 -0
- package/src/RTCDataChannel.ts +190 -0
- package/src/RTCDataChannelEvent.ts +28 -0
- package/src/RTCDataPacketCryptor.ts +90 -0
- package/src/RTCDataPacketCryptorFactory.ts +25 -0
- package/src/RTCErrorEvent.ts +21 -0
- package/src/RTCFrameCryptor.ts +163 -0
- package/src/RTCFrameCryptorFactory.ts +102 -0
- package/src/RTCIceCandidate.ts +29 -0
- package/src/RTCIceCandidateEvent.ts +26 -0
- package/src/RTCKeyProvider.ts +117 -0
- package/src/RTCPIPView.tsx +47 -0
- package/src/RTCPIPView.web.tsx +18 -0
- package/src/RTCPeerConnection.ts +832 -0
- package/src/RTCRtcpParameters.ts +23 -0
- package/src/RTCRtpCapabilities.ts +16 -0
- package/src/RTCRtpCodecCapability.ts +13 -0
- package/src/RTCRtpCodecParameters.ts +44 -0
- package/src/RTCRtpEncodingParameters.ts +90 -0
- package/src/RTCRtpHeaderExtension.ts +27 -0
- package/src/RTCRtpParameters.ts +37 -0
- package/src/RTCRtpReceiveParameters.ts +7 -0
- package/src/RTCRtpReceiver.ts +60 -0
- package/src/RTCRtpSendParameters.ts +63 -0
- package/src/RTCRtpSender.ts +78 -0
- package/src/RTCRtpTransceiver.ts +107 -0
- package/src/RTCSessionDescription.ts +30 -0
- package/src/RTCTrackEvent.ts +42 -0
- package/src/RTCUtil.ts +211 -0
- package/src/RTCView.ts +122 -0
- package/src/RTCView.web.tsx +82 -0
- package/src/ScreenCapturePickerView.ts +4 -0
- package/src/ScreenCapturePickerView.web.tsx +3 -0
- package/src/getDisplayMedia.ts +30 -0
- package/src/getUserMedia.ts +111 -0
- package/src/index.ts +107 -0
- package/src/index.web.ts +191 -0
- package/src/webStream.ts +33 -0
- package/tools/format.sh +6 -0
- package/tools/release.sh +45 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,1643 @@
|
|
|
1
|
+
package com.oney.WebRTCModule;
|
|
2
|
+
|
|
3
|
+
import android.util.Log;
|
|
4
|
+
import android.util.Pair;
|
|
5
|
+
import android.util.SparseArray;
|
|
6
|
+
|
|
7
|
+
import androidx.annotation.NonNull;
|
|
8
|
+
import androidx.annotation.Nullable;
|
|
9
|
+
|
|
10
|
+
import com.facebook.react.bridge.Arguments;
|
|
11
|
+
import com.facebook.react.bridge.Callback;
|
|
12
|
+
import com.facebook.react.bridge.Promise;
|
|
13
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
14
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
15
|
+
import com.facebook.react.bridge.ReactMethod;
|
|
16
|
+
import com.facebook.react.bridge.ReadableArray;
|
|
17
|
+
import com.facebook.react.bridge.ReadableMap;
|
|
18
|
+
import com.facebook.react.bridge.ReadableMapKeySetIterator;
|
|
19
|
+
import com.facebook.react.bridge.ReadableType;
|
|
20
|
+
import com.facebook.react.bridge.WritableArray;
|
|
21
|
+
import com.facebook.react.bridge.WritableMap;
|
|
22
|
+
import com.facebook.react.module.annotations.ReactModule;
|
|
23
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
|
24
|
+
import com.oney.WebRTCModule.webrtcutils.H264AndSoftwareVideoDecoderFactory;
|
|
25
|
+
import com.oney.WebRTCModule.webrtcutils.H264AndSoftwareVideoEncoderFactory;
|
|
26
|
+
import com.oney.WebRTCModule.palabra.PalabraClient;
|
|
27
|
+
import com.oney.WebRTCModule.palabra.PalabraConfig;
|
|
28
|
+
import com.oney.WebRTCModule.palabra.PalabraListener;
|
|
29
|
+
|
|
30
|
+
import org.webrtc.AddIceObserver;
|
|
31
|
+
import org.webrtc.AudioProcessingFactory;
|
|
32
|
+
import org.webrtc.AudioTrack;
|
|
33
|
+
import org.webrtc.CryptoOptions;
|
|
34
|
+
import org.webrtc.EglBase;
|
|
35
|
+
import org.webrtc.IceCandidate;
|
|
36
|
+
import org.webrtc.Loggable;
|
|
37
|
+
import org.webrtc.Logging;
|
|
38
|
+
import org.webrtc.MediaConstraints;
|
|
39
|
+
import org.webrtc.MediaStream;
|
|
40
|
+
import org.webrtc.MediaStreamTrack;
|
|
41
|
+
import org.webrtc.PeerConnection;
|
|
42
|
+
import org.webrtc.PeerConnectionFactory;
|
|
43
|
+
import org.webrtc.RTCStatsReport;
|
|
44
|
+
import org.webrtc.RtpCapabilities;
|
|
45
|
+
import org.webrtc.RtpParameters;
|
|
46
|
+
import org.webrtc.RtpSender;
|
|
47
|
+
import org.webrtc.RtpTransceiver;
|
|
48
|
+
import org.webrtc.SdpObserver;
|
|
49
|
+
import org.webrtc.SessionDescription;
|
|
50
|
+
import org.webrtc.SoftwareVideoDecoderFactory;
|
|
51
|
+
import org.webrtc.SoftwareVideoEncoderFactory;
|
|
52
|
+
import org.webrtc.VideoDecoderFactory;
|
|
53
|
+
import org.webrtc.VideoEncoderFactory;
|
|
54
|
+
import org.webrtc.VideoTrack;
|
|
55
|
+
import org.webrtc.audio.AudioDeviceModule;
|
|
56
|
+
import org.webrtc.audio.JavaAudioDeviceModule;
|
|
57
|
+
|
|
58
|
+
import java.util.ArrayList;
|
|
59
|
+
import java.util.HashMap;
|
|
60
|
+
import java.util.List;
|
|
61
|
+
import java.util.Map;
|
|
62
|
+
import java.util.Objects;
|
|
63
|
+
import java.util.concurrent.Callable;
|
|
64
|
+
import java.util.concurrent.ExecutionException;
|
|
65
|
+
|
|
66
|
+
@ReactModule(name = "WebRTCModule")
|
|
67
|
+
public class WebRTCModule extends ReactContextBaseJavaModule {
|
|
68
|
+
static final String TAG = WebRTCModule.class.getCanonicalName();
|
|
69
|
+
|
|
70
|
+
PeerConnectionFactory mFactory;
|
|
71
|
+
VideoEncoderFactory mVideoEncoderFactory;
|
|
72
|
+
VideoDecoderFactory mVideoDecoderFactory;
|
|
73
|
+
AudioDeviceModule mAudioDeviceModule;
|
|
74
|
+
|
|
75
|
+
// Need to expose the peer connection codec factories here to get capabilities
|
|
76
|
+
private final SparseArray<PeerConnectionObserver> mPeerConnectionObservers;
|
|
77
|
+
final Map<String, MediaStream> localStreams;
|
|
78
|
+
|
|
79
|
+
private final GetUserMediaImpl getUserMediaImpl;
|
|
80
|
+
|
|
81
|
+
private PalabraClient palabraClient;
|
|
82
|
+
|
|
83
|
+
public WebRTCModule(ReactApplicationContext reactContext) {
|
|
84
|
+
super(reactContext);
|
|
85
|
+
|
|
86
|
+
mPeerConnectionObservers = new SparseArray<>();
|
|
87
|
+
localStreams = new HashMap<>();
|
|
88
|
+
|
|
89
|
+
WebRTCModuleOptions options = WebRTCModuleOptions.getInstance();
|
|
90
|
+
|
|
91
|
+
AudioDeviceModule adm = options.audioDeviceModule;
|
|
92
|
+
VideoEncoderFactory encoderFactory = options.videoEncoderFactory;
|
|
93
|
+
VideoDecoderFactory decoderFactory = options.videoDecoderFactory;
|
|
94
|
+
Loggable injectableLogger = options.injectableLogger;
|
|
95
|
+
Logging.Severity loggingSeverity = options.loggingSeverity;
|
|
96
|
+
String fieldTrials = options.fieldTrials;
|
|
97
|
+
|
|
98
|
+
PeerConnectionFactory.initialize(PeerConnectionFactory.InitializationOptions.builder(reactContext)
|
|
99
|
+
.setFieldTrials(fieldTrials)
|
|
100
|
+
.setNativeLibraryLoader(new LibraryLoader())
|
|
101
|
+
.setInjectableLogger(injectableLogger, loggingSeverity)
|
|
102
|
+
.createInitializationOptions());
|
|
103
|
+
|
|
104
|
+
if (injectableLogger == null && loggingSeverity != null) {
|
|
105
|
+
Logging.enableLogToDebugOutput(loggingSeverity);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (encoderFactory == null || decoderFactory == null) {
|
|
109
|
+
// Initialize EGL context required for HW acceleration.
|
|
110
|
+
EglBase.Context eglContext = EglUtils.getRootEglBaseContext();
|
|
111
|
+
|
|
112
|
+
if (eglContext != null) {
|
|
113
|
+
encoderFactory = new H264AndSoftwareVideoEncoderFactory(eglContext);
|
|
114
|
+
decoderFactory = new H264AndSoftwareVideoDecoderFactory(eglContext);
|
|
115
|
+
} else {
|
|
116
|
+
encoderFactory = new SoftwareVideoEncoderFactory();
|
|
117
|
+
decoderFactory = new SoftwareVideoDecoderFactory();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (adm == null) {
|
|
122
|
+
adm = JavaAudioDeviceModule.builder(reactContext).createAudioDeviceModule();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
AudioProcessingFactory audioProcessingFactory = null;
|
|
126
|
+
try {
|
|
127
|
+
if (options.audioProcessingFactoryFactory != null) {
|
|
128
|
+
audioProcessingFactory = options.audioProcessingFactoryFactory.call();
|
|
129
|
+
}
|
|
130
|
+
} catch (Exception e) {
|
|
131
|
+
// do nothing.
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
Log.d(TAG, "Using video encoder factory: " + encoderFactory.getClass().getCanonicalName());
|
|
135
|
+
Log.d(TAG, "Using video decoder factory: " + decoderFactory.getClass().getCanonicalName());
|
|
136
|
+
|
|
137
|
+
PeerConnectionFactory.Builder pcFactoryBuilder = PeerConnectionFactory.builder()
|
|
138
|
+
.setAudioDeviceModule(adm)
|
|
139
|
+
.setVideoEncoderFactory(encoderFactory)
|
|
140
|
+
.setVideoDecoderFactory(decoderFactory);
|
|
141
|
+
|
|
142
|
+
if (audioProcessingFactory != null) {
|
|
143
|
+
pcFactoryBuilder.setAudioProcessingFactory(audioProcessingFactory);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
mFactory = pcFactoryBuilder.createPeerConnectionFactory();
|
|
147
|
+
|
|
148
|
+
// PeerConnectionFactory now owns the adm native pointer, and we don't need it anymore.
|
|
149
|
+
adm.release();
|
|
150
|
+
|
|
151
|
+
// Saving the encoder and decoder factories to get codec info later when needed.
|
|
152
|
+
mVideoEncoderFactory = encoderFactory;
|
|
153
|
+
mVideoDecoderFactory = decoderFactory;
|
|
154
|
+
mAudioDeviceModule = adm;
|
|
155
|
+
|
|
156
|
+
getUserMediaImpl = new GetUserMediaImpl(this, reactContext);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
@NonNull
|
|
160
|
+
@Override
|
|
161
|
+
public String getName() {
|
|
162
|
+
return "WebRTCModule";
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
public PeerConnectionObserver getPeerConnectionObserver(int id) {
|
|
166
|
+
return mPeerConnectionObservers.get(id);
|
|
167
|
+
}
|
|
168
|
+
private PeerConnection getPeerConnection(int id) {
|
|
169
|
+
PeerConnectionObserver pco = mPeerConnectionObservers.get(id);
|
|
170
|
+
return (pco == null) ? null : pco.getPeerConnection();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
void sendEvent(String eventName, @Nullable ReadableMap params) {
|
|
174
|
+
getReactApplicationContext()
|
|
175
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
|
176
|
+
.emit(eventName, params);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
private PeerConnection.IceServer createIceServer(String url) {
|
|
180
|
+
return PeerConnection.IceServer.builder(url).createIceServer();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
private PeerConnection.IceServer createIceServer(String url, String username, String credential) {
|
|
184
|
+
return PeerConnection.IceServer.builder(url).setUsername(username).setPassword(credential).createIceServer();
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
private List<PeerConnection.IceServer> createIceServers(ReadableArray iceServersArray) {
|
|
188
|
+
final int size = (iceServersArray == null) ? 0 : iceServersArray.size();
|
|
189
|
+
List<PeerConnection.IceServer> iceServers = new ArrayList<>(size);
|
|
190
|
+
for (int i = 0; i < size; i++) {
|
|
191
|
+
ReadableMap iceServerMap = iceServersArray.getMap(i);
|
|
192
|
+
boolean hasUsernameAndCredential = iceServerMap.hasKey("username") && iceServerMap.hasKey("credential");
|
|
193
|
+
if (iceServerMap.hasKey("urls")) {
|
|
194
|
+
switch (iceServerMap.getType("urls")) {
|
|
195
|
+
case String:
|
|
196
|
+
if (hasUsernameAndCredential) {
|
|
197
|
+
iceServers.add(createIceServer(iceServerMap.getString("urls"),
|
|
198
|
+
iceServerMap.getString("username"),
|
|
199
|
+
iceServerMap.getString("credential")));
|
|
200
|
+
} else {
|
|
201
|
+
iceServers.add(createIceServer(iceServerMap.getString("urls")));
|
|
202
|
+
}
|
|
203
|
+
break;
|
|
204
|
+
case Array:
|
|
205
|
+
ReadableArray urls = iceServerMap.getArray("urls");
|
|
206
|
+
for (int j = 0; j < urls.size(); j++) {
|
|
207
|
+
String url = urls.getString(j);
|
|
208
|
+
if (hasUsernameAndCredential) {
|
|
209
|
+
iceServers.add(createIceServer(
|
|
210
|
+
url, iceServerMap.getString("username"), iceServerMap.getString("credential")));
|
|
211
|
+
} else {
|
|
212
|
+
iceServers.add(createIceServer(url));
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return iceServers;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
private PeerConnection.RTCConfiguration parseRTCConfiguration(ReadableMap map) {
|
|
223
|
+
ReadableArray iceServersArray = null;
|
|
224
|
+
if (map != null && map.hasKey("iceServers")) {
|
|
225
|
+
iceServersArray = map.getArray("iceServers");
|
|
226
|
+
}
|
|
227
|
+
List<PeerConnection.IceServer> iceServers = createIceServers(iceServersArray);
|
|
228
|
+
|
|
229
|
+
PeerConnection.RTCConfiguration conf = new PeerConnection.RTCConfiguration(iceServers);
|
|
230
|
+
conf.sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN;
|
|
231
|
+
|
|
232
|
+
// Required for perfect negotiation.
|
|
233
|
+
conf.enableImplicitRollback = true;
|
|
234
|
+
|
|
235
|
+
// Enable GCM ciphers.
|
|
236
|
+
CryptoOptions cryptoOptions = CryptoOptions.builder()
|
|
237
|
+
.setEnableGcmCryptoSuites(true)
|
|
238
|
+
.setEnableAes128Sha1_32CryptoCipher(false)
|
|
239
|
+
.setEnableEncryptedRtpHeaderExtensions(false)
|
|
240
|
+
.setRequireFrameEncryption(false)
|
|
241
|
+
.createCryptoOptions();
|
|
242
|
+
conf.cryptoOptions = cryptoOptions;
|
|
243
|
+
|
|
244
|
+
if (map == null) {
|
|
245
|
+
return conf;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// iceTransportPolicy (public api)
|
|
249
|
+
if (map.hasKey("iceTransportPolicy") && map.getType("iceTransportPolicy") == ReadableType.String) {
|
|
250
|
+
final String v = map.getString("iceTransportPolicy");
|
|
251
|
+
if (v != null) {
|
|
252
|
+
switch (v) {
|
|
253
|
+
case "all": // public
|
|
254
|
+
conf.iceTransportsType = PeerConnection.IceTransportsType.ALL;
|
|
255
|
+
break;
|
|
256
|
+
case "relay": // public
|
|
257
|
+
conf.iceTransportsType = PeerConnection.IceTransportsType.RELAY;
|
|
258
|
+
break;
|
|
259
|
+
case "nohost":
|
|
260
|
+
conf.iceTransportsType = PeerConnection.IceTransportsType.NOHOST;
|
|
261
|
+
break;
|
|
262
|
+
case "none":
|
|
263
|
+
conf.iceTransportsType = PeerConnection.IceTransportsType.NONE;
|
|
264
|
+
break;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// bundlePolicy (public api)
|
|
270
|
+
if (map.hasKey("bundlePolicy") && map.getType("bundlePolicy") == ReadableType.String) {
|
|
271
|
+
final String v = map.getString("bundlePolicy");
|
|
272
|
+
if (v != null) {
|
|
273
|
+
switch (v) {
|
|
274
|
+
case "balanced": // public
|
|
275
|
+
conf.bundlePolicy = PeerConnection.BundlePolicy.BALANCED;
|
|
276
|
+
break;
|
|
277
|
+
case "max-compat": // public
|
|
278
|
+
conf.bundlePolicy = PeerConnection.BundlePolicy.MAXCOMPAT;
|
|
279
|
+
break;
|
|
280
|
+
case "max-bundle": // public
|
|
281
|
+
conf.bundlePolicy = PeerConnection.BundlePolicy.MAXBUNDLE;
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// rtcpMuxPolicy (public api)
|
|
288
|
+
if (map.hasKey("rtcpMuxPolicy") && map.getType("rtcpMuxPolicy") == ReadableType.String) {
|
|
289
|
+
final String v = map.getString("rtcpMuxPolicy");
|
|
290
|
+
if (v != null) {
|
|
291
|
+
switch (v) {
|
|
292
|
+
case "negotiate": // public
|
|
293
|
+
conf.rtcpMuxPolicy = PeerConnection.RtcpMuxPolicy.NEGOTIATE;
|
|
294
|
+
break;
|
|
295
|
+
case "require": // public
|
|
296
|
+
conf.rtcpMuxPolicy = PeerConnection.RtcpMuxPolicy.REQUIRE;
|
|
297
|
+
break;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// FIXME: peerIdentity of type DOMString (public api)
|
|
303
|
+
// FIXME: certificates of type sequence<RTCCertificate> (public api)
|
|
304
|
+
|
|
305
|
+
// iceCandidatePoolSize of type unsigned short, defaulting to 0
|
|
306
|
+
if (map.hasKey("iceCandidatePoolSize") && map.getType("iceCandidatePoolSize") == ReadableType.Number) {
|
|
307
|
+
final int v = map.getInt("iceCandidatePoolSize");
|
|
308
|
+
if (v > 0) {
|
|
309
|
+
conf.iceCandidatePoolSize = v;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// === below is private api in webrtc ===
|
|
314
|
+
|
|
315
|
+
// tcpCandidatePolicy (private api)
|
|
316
|
+
if (map.hasKey("tcpCandidatePolicy") && map.getType("tcpCandidatePolicy") == ReadableType.String) {
|
|
317
|
+
final String v = map.getString("tcpCandidatePolicy");
|
|
318
|
+
if (v != null) {
|
|
319
|
+
switch (v) {
|
|
320
|
+
case "enabled":
|
|
321
|
+
conf.tcpCandidatePolicy = PeerConnection.TcpCandidatePolicy.ENABLED;
|
|
322
|
+
break;
|
|
323
|
+
case "disabled":
|
|
324
|
+
conf.tcpCandidatePolicy = PeerConnection.TcpCandidatePolicy.DISABLED;
|
|
325
|
+
break;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// candidateNetworkPolicy (private api)
|
|
331
|
+
if (map.hasKey("candidateNetworkPolicy") && map.getType("candidateNetworkPolicy") == ReadableType.String) {
|
|
332
|
+
final String v = map.getString("candidateNetworkPolicy");
|
|
333
|
+
if (v != null) {
|
|
334
|
+
switch (v) {
|
|
335
|
+
case "all":
|
|
336
|
+
conf.candidateNetworkPolicy = PeerConnection.CandidateNetworkPolicy.ALL;
|
|
337
|
+
break;
|
|
338
|
+
case "low_cost":
|
|
339
|
+
conf.candidateNetworkPolicy = PeerConnection.CandidateNetworkPolicy.LOW_COST;
|
|
340
|
+
break;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// KeyType (private api)
|
|
346
|
+
if (map.hasKey("keyType") && map.getType("keyType") == ReadableType.String) {
|
|
347
|
+
final String v = map.getString("keyType");
|
|
348
|
+
if (v != null) {
|
|
349
|
+
switch (v) {
|
|
350
|
+
case "RSA":
|
|
351
|
+
conf.keyType = PeerConnection.KeyType.RSA;
|
|
352
|
+
break;
|
|
353
|
+
case "ECDSA":
|
|
354
|
+
conf.keyType = PeerConnection.KeyType.ECDSA;
|
|
355
|
+
break;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// continualGatheringPolicy (private api)
|
|
361
|
+
if (map.hasKey("continualGatheringPolicy") && map.getType("continualGatheringPolicy") == ReadableType.String) {
|
|
362
|
+
final String v = map.getString("continualGatheringPolicy");
|
|
363
|
+
if (v != null) {
|
|
364
|
+
switch (v) {
|
|
365
|
+
case "gather_once":
|
|
366
|
+
conf.continualGatheringPolicy = PeerConnection.ContinualGatheringPolicy.GATHER_ONCE;
|
|
367
|
+
break;
|
|
368
|
+
case "gather_continually":
|
|
369
|
+
conf.continualGatheringPolicy = PeerConnection.ContinualGatheringPolicy.GATHER_CONTINUALLY;
|
|
370
|
+
break;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// audioJitterBufferMaxPackets (private api)
|
|
376
|
+
if (map.hasKey("audioJitterBufferMaxPackets")
|
|
377
|
+
&& map.getType("audioJitterBufferMaxPackets") == ReadableType.Number) {
|
|
378
|
+
final int v = map.getInt("audioJitterBufferMaxPackets");
|
|
379
|
+
if (v > 0) {
|
|
380
|
+
conf.audioJitterBufferMaxPackets = v;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// iceConnectionReceivingTimeout (private api)
|
|
385
|
+
if (map.hasKey("iceConnectionReceivingTimeout")
|
|
386
|
+
&& map.getType("iceConnectionReceivingTimeout") == ReadableType.Number) {
|
|
387
|
+
final int v = map.getInt("iceConnectionReceivingTimeout");
|
|
388
|
+
conf.iceConnectionReceivingTimeout = v;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// iceBackupCandidatePairPingInterval (private api)
|
|
392
|
+
if (map.hasKey("iceBackupCandidatePairPingInterval")
|
|
393
|
+
&& map.getType("iceBackupCandidatePairPingInterval") == ReadableType.Number) {
|
|
394
|
+
final int v = map.getInt("iceBackupCandidatePairPingInterval");
|
|
395
|
+
conf.iceBackupCandidatePairPingInterval = v;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// audioJitterBufferFastAccelerate (private api)
|
|
399
|
+
if (map.hasKey("audioJitterBufferFastAccelerate")
|
|
400
|
+
&& map.getType("audioJitterBufferFastAccelerate") == ReadableType.Boolean) {
|
|
401
|
+
final boolean v = map.getBoolean("audioJitterBufferFastAccelerate");
|
|
402
|
+
conf.audioJitterBufferFastAccelerate = v;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// pruneTurnPorts (private api)
|
|
406
|
+
if (map.hasKey("pruneTurnPorts") && map.getType("pruneTurnPorts") == ReadableType.Boolean) {
|
|
407
|
+
final boolean v = map.getBoolean("pruneTurnPorts");
|
|
408
|
+
conf.pruneTurnPorts = v;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// presumeWritableWhenFullyRelayed (private api)
|
|
412
|
+
if (map.hasKey("presumeWritableWhenFullyRelayed")
|
|
413
|
+
&& map.getType("presumeWritableWhenFullyRelayed") == ReadableType.Boolean) {
|
|
414
|
+
final boolean v = map.getBoolean("presumeWritableWhenFullyRelayed");
|
|
415
|
+
conf.presumeWritableWhenFullyRelayed = v;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
return conf;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
422
|
+
public boolean peerConnectionInit(ReadableMap configuration, int id) {
|
|
423
|
+
PeerConnection.RTCConfiguration rtcConfiguration = parseRTCConfiguration(configuration);
|
|
424
|
+
|
|
425
|
+
try {
|
|
426
|
+
return (boolean) ThreadUtils
|
|
427
|
+
.submitToExecutor(() -> {
|
|
428
|
+
PeerConnectionObserver observer = new PeerConnectionObserver(this, id);
|
|
429
|
+
PeerConnection peerConnection = mFactory.createPeerConnection(rtcConfiguration, observer);
|
|
430
|
+
if (peerConnection == null) {
|
|
431
|
+
return false;
|
|
432
|
+
}
|
|
433
|
+
observer.setPeerConnection(peerConnection);
|
|
434
|
+
mPeerConnectionObservers.put(id, observer);
|
|
435
|
+
return true;
|
|
436
|
+
})
|
|
437
|
+
.get();
|
|
438
|
+
} catch (ExecutionException | InterruptedException e) {
|
|
439
|
+
e.printStackTrace();
|
|
440
|
+
throw new RuntimeException(e);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
MediaStream getStreamForReactTag(String streamReactTag) {
|
|
445
|
+
// This function _only_ gets called from WebRTCView, in the UI thread.
|
|
446
|
+
// Hence make sure we run this code in the executor or we run at the risk
|
|
447
|
+
// of being out of sync.
|
|
448
|
+
try {
|
|
449
|
+
return (MediaStream) ThreadUtils
|
|
450
|
+
.submitToExecutor((Callable<Object>) () -> {
|
|
451
|
+
MediaStream stream = localStreams.get(streamReactTag);
|
|
452
|
+
|
|
453
|
+
if (stream != null) {
|
|
454
|
+
return stream;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
for (int i = 0, size = mPeerConnectionObservers.size(); i < size; i++) {
|
|
458
|
+
PeerConnectionObserver pco = mPeerConnectionObservers.valueAt(i);
|
|
459
|
+
stream = pco.remoteStreams.get(streamReactTag);
|
|
460
|
+
if (stream != null) {
|
|
461
|
+
return stream;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
return null;
|
|
466
|
+
})
|
|
467
|
+
.get();
|
|
468
|
+
} catch (ExecutionException | InterruptedException e) {
|
|
469
|
+
return null;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
public MediaStreamTrack getTrack(int pcId, String trackId) {
|
|
474
|
+
if (pcId == -1) {
|
|
475
|
+
return getLocalTrack(trackId);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
PeerConnectionObserver pco = mPeerConnectionObservers.get(pcId);
|
|
479
|
+
if (pco == null) {
|
|
480
|
+
Log.d(TAG, "getTrack(): could not find PeerConnection");
|
|
481
|
+
return null;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
return pco.remoteTracks.get(trackId);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
MediaStreamTrack getLocalTrack(String trackId) {
|
|
488
|
+
return getUserMediaImpl.getTrack(trackId);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
public VideoTrack createVideoTrack(AbstractVideoCaptureController videoCaptureController) {
|
|
492
|
+
return getUserMediaImpl.createVideoTrack(videoCaptureController);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
public void createStream(
|
|
496
|
+
MediaStreamTrack[] tracks, GetUserMediaImpl.BiConsumer<String, ArrayList<WritableMap>> successCallback) {
|
|
497
|
+
getUserMediaImpl.createStream(tracks, successCallback);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Turns an "options" <tt>ReadableMap</tt> into a <tt>MediaConstraints</tt> object.
|
|
502
|
+
*
|
|
503
|
+
* @param options A <tt>ReadableMap</tt> which represents a JavaScript
|
|
504
|
+
* object specifying the options to be parsed into a
|
|
505
|
+
* <tt>MediaConstraints</tt> instance.
|
|
506
|
+
* @return A new <tt>MediaConstraints</tt> instance initialized with the
|
|
507
|
+
* mandatory keys and values specified by <tt>options</tt>.
|
|
508
|
+
*/
|
|
509
|
+
MediaConstraints constraintsForOptions(ReadableMap options) {
|
|
510
|
+
MediaConstraints mediaConstraints = new MediaConstraints();
|
|
511
|
+
ReadableMapKeySetIterator keyIterator = options.keySetIterator();
|
|
512
|
+
|
|
513
|
+
while (keyIterator.hasNextKey()) {
|
|
514
|
+
String key = keyIterator.nextKey();
|
|
515
|
+
String value = ReactBridgeUtil.getMapStrValue(options, key);
|
|
516
|
+
|
|
517
|
+
mediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair(key, value));
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
return mediaConstraints;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
524
|
+
public WritableMap peerConnectionAddTransceiver(int id, ReadableMap options) {
|
|
525
|
+
try {
|
|
526
|
+
return (WritableMap) ThreadUtils
|
|
527
|
+
.submitToExecutor((Callable<Object>) () -> {
|
|
528
|
+
PeerConnectionObserver pco = mPeerConnectionObservers.get(id);
|
|
529
|
+
if (pco == null) {
|
|
530
|
+
Log.d(TAG, "peerConnectionAddTransceiver() peerConnection is null");
|
|
531
|
+
return null;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
RtpTransceiver transceiver = null;
|
|
535
|
+
if (options.hasKey("type")) {
|
|
536
|
+
String kind = options.getString("type");
|
|
537
|
+
transceiver = pco.addTransceiver(SerializeUtils.parseMediaType(kind),
|
|
538
|
+
SerializeUtils.parseTransceiverOptions(options.getMap("init")));
|
|
539
|
+
} else if (options.hasKey("trackId")) {
|
|
540
|
+
String trackId = options.getString("trackId");
|
|
541
|
+
MediaStreamTrack track = getLocalTrack(trackId);
|
|
542
|
+
transceiver = pco.addTransceiver(
|
|
543
|
+
track, SerializeUtils.parseTransceiverOptions(options.getMap("init")));
|
|
544
|
+
|
|
545
|
+
} else {
|
|
546
|
+
// This should technically never happen as the JS side checks for that.
|
|
547
|
+
Log.d(TAG, "peerConnectionAddTransceiver() no type nor trackId provided in options");
|
|
548
|
+
return null;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
if (transceiver == null) {
|
|
552
|
+
Log.d(TAG, "peerConnectionAddTransceiver() Error adding transceiver");
|
|
553
|
+
return null;
|
|
554
|
+
}
|
|
555
|
+
WritableMap params = Arguments.createMap();
|
|
556
|
+
// We need to get a unique order at which the transceiver was created
|
|
557
|
+
// to reorder the cached array of transceivers on the JS layer.
|
|
558
|
+
params.putInt("transceiverOrder", pco.getNextTransceiverId());
|
|
559
|
+
params.putMap("transceiver", SerializeUtils.serializeTransceiver(id, transceiver));
|
|
560
|
+
return params;
|
|
561
|
+
})
|
|
562
|
+
.get();
|
|
563
|
+
} catch (InterruptedException | ExecutionException e) {
|
|
564
|
+
Log.d(TAG, "peerConnectionAddTransceiver() " + e.getMessage());
|
|
565
|
+
return null;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
570
|
+
public WritableMap peerConnectionAddTrack(int id, String trackId, ReadableMap options) {
|
|
571
|
+
try {
|
|
572
|
+
return (WritableMap) ThreadUtils
|
|
573
|
+
.submitToExecutor((Callable<Object>) () -> {
|
|
574
|
+
PeerConnectionObserver pco = mPeerConnectionObservers.get(id);
|
|
575
|
+
if (pco == null) {
|
|
576
|
+
Log.d(TAG, "peerConnectionAddTrack() peerConnection is null");
|
|
577
|
+
return null;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
MediaStreamTrack track = getLocalTrack(trackId);
|
|
581
|
+
if (track == null) {
|
|
582
|
+
Log.w(TAG, "peerConnectionAddTrack() couldn't find track " + trackId);
|
|
583
|
+
return null;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
List<String> streamIds = new ArrayList<>();
|
|
587
|
+
if (options.hasKey("streamIds")) {
|
|
588
|
+
ReadableArray rawStreamIds = options.getArray("streamIds");
|
|
589
|
+
if (rawStreamIds != null) {
|
|
590
|
+
for (int i = 0; i < rawStreamIds.size(); i++) {
|
|
591
|
+
streamIds.add(rawStreamIds.getString(i));
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
RtpSender sender = pco.getPeerConnection().addTrack(track, streamIds);
|
|
596
|
+
|
|
597
|
+
// Need to get the corresponding transceiver as well
|
|
598
|
+
RtpTransceiver transceiver = pco.getTransceiver(sender.id());
|
|
599
|
+
|
|
600
|
+
// We need the transceiver creation order to reorder the transceivers array
|
|
601
|
+
// in the JS layer.
|
|
602
|
+
WritableMap params = Arguments.createMap();
|
|
603
|
+
params.putInt("transceiverOrder", pco.getNextTransceiverId());
|
|
604
|
+
params.putMap("transceiver", SerializeUtils.serializeTransceiver(id, transceiver));
|
|
605
|
+
params.putMap("sender", SerializeUtils.serializeSender(id, sender));
|
|
606
|
+
return params;
|
|
607
|
+
})
|
|
608
|
+
.get();
|
|
609
|
+
} catch (InterruptedException | ExecutionException e) {
|
|
610
|
+
Log.d(TAG, "peerConnectionAddTrack() " + e.getMessage());
|
|
611
|
+
return null;
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
616
|
+
public boolean peerConnectionRemoveTrack(int id, String senderId) {
|
|
617
|
+
try {
|
|
618
|
+
return (boolean) ThreadUtils
|
|
619
|
+
.submitToExecutor((Callable<Object>) () -> {
|
|
620
|
+
PeerConnectionObserver pco = mPeerConnectionObservers.get(id);
|
|
621
|
+
if (pco == null) {
|
|
622
|
+
Log.d(TAG, "peerConnectionRemoveTrack() peerConnection is null");
|
|
623
|
+
return false;
|
|
624
|
+
}
|
|
625
|
+
RtpSender sender = pco.getSender(senderId);
|
|
626
|
+
if (sender == null) {
|
|
627
|
+
Log.w(TAG, "peerConnectionRemoveTrack() sender is null");
|
|
628
|
+
return false;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
return pco.getPeerConnection().removeTrack(sender);
|
|
632
|
+
})
|
|
633
|
+
.get();
|
|
634
|
+
} catch (InterruptedException | ExecutionException e) {
|
|
635
|
+
Log.d(TAG, "peerConnectionRemoveTrack() " + e.getMessage());
|
|
636
|
+
return false;
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
@ReactMethod
|
|
641
|
+
public void senderSetParameters(int id, String senderId, ReadableMap options, Promise promise) {
|
|
642
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
643
|
+
try {
|
|
644
|
+
PeerConnectionObserver pco = mPeerConnectionObservers.get(id);
|
|
645
|
+
if (pco == null) {
|
|
646
|
+
Log.d(TAG, "senderSetParameters() peerConnectionObserver is null");
|
|
647
|
+
promise.reject(new Exception("Peer Connection is not initialized"));
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
RtpSender sender = pco.getSender(senderId);
|
|
652
|
+
if (sender == null) {
|
|
653
|
+
Log.w(TAG, "senderSetParameters() sender is null");
|
|
654
|
+
promise.reject(new Exception("Could not get sender"));
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
RtpParameters params = sender.getParameters();
|
|
659
|
+
params = SerializeUtils.updateRtpParameters(options, params);
|
|
660
|
+
sender.setParameters(params);
|
|
661
|
+
promise.resolve(SerializeUtils.serializeRtpParameters(sender.getParameters()));
|
|
662
|
+
} catch (Exception e) {
|
|
663
|
+
Log.d(TAG, "senderSetParameters: " + e.getMessage());
|
|
664
|
+
promise.reject(e);
|
|
665
|
+
}
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
@ReactMethod
|
|
670
|
+
public void transceiverStop(int id, String senderId, Promise promise) {
|
|
671
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
672
|
+
try {
|
|
673
|
+
PeerConnectionObserver pco = mPeerConnectionObservers.get(id);
|
|
674
|
+
if (pco == null) {
|
|
675
|
+
Log.d(TAG, "transceiverStop() peerConnectionObserver is null");
|
|
676
|
+
promise.reject(new Exception("Peer Connection is not initialized"));
|
|
677
|
+
return;
|
|
678
|
+
}
|
|
679
|
+
RtpTransceiver transceiver = pco.getTransceiver(senderId);
|
|
680
|
+
if (transceiver == null) {
|
|
681
|
+
Log.w(TAG, "transceiverStop() transceiver is null");
|
|
682
|
+
promise.reject(new Exception("Could not get transceiver"));
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
transceiver.stopStandard();
|
|
687
|
+
promise.resolve(true);
|
|
688
|
+
} catch (Exception e) {
|
|
689
|
+
Log.d(TAG, "transceiverStop(): " + e.getMessage());
|
|
690
|
+
promise.reject(e);
|
|
691
|
+
}
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
@ReactMethod
|
|
696
|
+
public void senderReplaceTrack(int id, String senderId, String trackId, Promise promise) {
|
|
697
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
698
|
+
try {
|
|
699
|
+
PeerConnectionObserver pco = mPeerConnectionObservers.get(id);
|
|
700
|
+
if (pco == null) {
|
|
701
|
+
Log.d(TAG, "senderReplaceTrack() peerConnectionObserver is null");
|
|
702
|
+
promise.reject(new Exception("Peer Connection is not initialized"));
|
|
703
|
+
return;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
RtpSender sender = pco.getSender(senderId);
|
|
707
|
+
if (sender == null) {
|
|
708
|
+
Log.w(TAG, "senderReplaceTrack() sender is null");
|
|
709
|
+
promise.reject(new Exception("Could not get sender"));
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
MediaStreamTrack track = getLocalTrack(trackId);
|
|
714
|
+
sender.setTrack(track, false);
|
|
715
|
+
promise.resolve(true);
|
|
716
|
+
} catch (Exception e) {
|
|
717
|
+
Log.d(TAG, "senderReplaceTrack(): " + e.getMessage());
|
|
718
|
+
promise.reject(e);
|
|
719
|
+
}
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
@ReactMethod
|
|
724
|
+
public void transceiverSetDirection(int id, String senderId, String direction, Promise promise) {
|
|
725
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
726
|
+
WritableMap identifier = Arguments.createMap();
|
|
727
|
+
WritableMap params = Arguments.createMap();
|
|
728
|
+
identifier.putInt("peerConnectionId", id);
|
|
729
|
+
identifier.putString("transceiverId", senderId);
|
|
730
|
+
try {
|
|
731
|
+
PeerConnectionObserver pco = mPeerConnectionObservers.get(id);
|
|
732
|
+
if (pco == null) {
|
|
733
|
+
Log.d(TAG, "transceiverSetDirection() peerConnectionObserver is null");
|
|
734
|
+
promise.reject(new Exception("Peer Connection is not initialized"));
|
|
735
|
+
return;
|
|
736
|
+
}
|
|
737
|
+
RtpTransceiver transceiver = pco.getTransceiver(senderId);
|
|
738
|
+
if (transceiver == null) {
|
|
739
|
+
Log.d(TAG, "transceiverSetDirection() transceiver is null");
|
|
740
|
+
promise.reject(new Exception("Could not get sender"));
|
|
741
|
+
return;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
transceiver.setDirection(SerializeUtils.parseDirection(direction));
|
|
745
|
+
|
|
746
|
+
promise.resolve(true);
|
|
747
|
+
} catch (Exception e) {
|
|
748
|
+
Log.d(TAG, "transceiverSetDirection(): " + e.getMessage());
|
|
749
|
+
promise.reject(e);
|
|
750
|
+
}
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
755
|
+
public boolean transceiverSetCodecPreferences(int id, String senderId, ReadableArray codecPreferences) {
|
|
756
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
757
|
+
WritableMap identifier = Arguments.createMap();
|
|
758
|
+
WritableMap params = Arguments.createMap();
|
|
759
|
+
identifier.putInt("peerConnectionId", id);
|
|
760
|
+
identifier.putString("transceiverId", senderId);
|
|
761
|
+
try {
|
|
762
|
+
PeerConnectionObserver pco = mPeerConnectionObservers.get(id);
|
|
763
|
+
if (pco == null) {
|
|
764
|
+
Log.d(TAG, "transceiverSetDirection() peerConnectionObserver is null");
|
|
765
|
+
return;
|
|
766
|
+
}
|
|
767
|
+
RtpTransceiver transceiver = pco.getTransceiver(senderId);
|
|
768
|
+
if (transceiver == null) {
|
|
769
|
+
Log.d(TAG, "transceiverSetDirection() transceiver is null");
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
// Convert JSON codec capabilities to the actual objects.
|
|
774
|
+
RtpTransceiver.RtpTransceiverDirection direction = transceiver.getDirection();
|
|
775
|
+
List<Pair<Map<String, Object>, RtpCapabilities.CodecCapability>> availableCodecs = new ArrayList<>();
|
|
776
|
+
|
|
777
|
+
if (direction.equals(RtpTransceiver.RtpTransceiverDirection.SEND_RECV)
|
|
778
|
+
|| direction.equals(RtpTransceiver.RtpTransceiverDirection.SEND_ONLY)) {
|
|
779
|
+
RtpCapabilities capabilities = mFactory.getRtpSenderCapabilities(transceiver.getMediaType());
|
|
780
|
+
for (RtpCapabilities.CodecCapability codec : capabilities.codecs) {
|
|
781
|
+
Map<String, Object> codecDict = SerializeUtils.serializeRtpCapabilitiesCodec(codec).toHashMap();
|
|
782
|
+
availableCodecs.add(new Pair<>(codecDict, codec));
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
if (direction.equals(RtpTransceiver.RtpTransceiverDirection.SEND_RECV)
|
|
787
|
+
|| direction.equals(RtpTransceiver.RtpTransceiverDirection.RECV_ONLY)) {
|
|
788
|
+
RtpCapabilities capabilities = mFactory.getRtpReceiverCapabilities(transceiver.getMediaType());
|
|
789
|
+
for (RtpCapabilities.CodecCapability codec : capabilities.codecs) {
|
|
790
|
+
Map<String, Object> codecDict = SerializeUtils.serializeRtpCapabilitiesCodec(codec).toHashMap();
|
|
791
|
+
availableCodecs.add(new Pair<>(codecDict, codec));
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
// Codec preferences is order sensitive.
|
|
796
|
+
List<RtpCapabilities.CodecCapability> codecsToSet = new ArrayList<>();
|
|
797
|
+
|
|
798
|
+
for (int i = 0; i < codecPreferences.size(); i++) {
|
|
799
|
+
Map<String, Object> codecPref = codecPreferences.getMap(i).toHashMap();
|
|
800
|
+
for (Pair<Map<String, Object>, RtpCapabilities.CodecCapability> pair : availableCodecs) {
|
|
801
|
+
Map<String, Object> availableCodecDict = pair.first;
|
|
802
|
+
if (codecPref.equals(availableCodecDict)) {
|
|
803
|
+
codecsToSet.add(pair.second);
|
|
804
|
+
break;
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
transceiver.setCodecPreferences(codecsToSet);
|
|
810
|
+
} catch (Exception e) {
|
|
811
|
+
Log.d(TAG, "transceiverSetCodecPreferences(): " + e.getMessage());
|
|
812
|
+
}
|
|
813
|
+
});
|
|
814
|
+
return true;
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
@ReactMethod
|
|
818
|
+
public void getDisplayMedia(Promise promise) {
|
|
819
|
+
ThreadUtils.runOnExecutor(() -> getUserMediaImpl.getDisplayMedia(promise));
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
@ReactMethod
|
|
823
|
+
public void getUserMedia(ReadableMap constraints, Callback successCallback, Callback errorCallback) {
|
|
824
|
+
ThreadUtils.runOnExecutor(() -> getUserMediaImpl.getUserMedia(constraints, successCallback, errorCallback));
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
@ReactMethod
|
|
828
|
+
public void enumerateDevices(Callback callback) {
|
|
829
|
+
ThreadUtils.runOnExecutor(() -> callback.invoke(getUserMediaImpl.enumerateDevices()));
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
@ReactMethod
|
|
833
|
+
public void mediaStreamCreate(String id) {
|
|
834
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
835
|
+
MediaStream mediaStream = mFactory.createLocalMediaStream(id);
|
|
836
|
+
localStreams.put(id, mediaStream);
|
|
837
|
+
});
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
@ReactMethod
|
|
841
|
+
public void mediaStreamAddTrack(String streamId, int pcId, String trackId) {
|
|
842
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
843
|
+
MediaStream stream = localStreams.get(streamId);
|
|
844
|
+
if (stream == null) {
|
|
845
|
+
Log.d(TAG, "mediaStreamAddTrack() could not find stream " + streamId);
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
MediaStreamTrack track = getTrack(pcId, trackId);
|
|
850
|
+
if (track == null) {
|
|
851
|
+
Log.d(TAG, "mediaStreamAddTrack() could not find track " + trackId);
|
|
852
|
+
return;
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
String kind = track.kind();
|
|
856
|
+
if ("audio".equals(kind)) {
|
|
857
|
+
stream.addTrack((AudioTrack) track);
|
|
858
|
+
} else if ("video".equals(kind)) {
|
|
859
|
+
stream.addTrack((VideoTrack) track);
|
|
860
|
+
}
|
|
861
|
+
});
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
@ReactMethod
|
|
865
|
+
public void mediaStreamRemoveTrack(String streamId, int pcId, String trackId) {
|
|
866
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
867
|
+
MediaStream stream = localStreams.get(streamId);
|
|
868
|
+
if (stream == null) {
|
|
869
|
+
Log.d(TAG, "mediaStreamRemoveTrack() could not find stream " + streamId);
|
|
870
|
+
return;
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
MediaStreamTrack track = getTrack(pcId, trackId);
|
|
874
|
+
if (track == null) {
|
|
875
|
+
Log.d(TAG, "mediaStreamRemoveTrack() could not find track " + trackId);
|
|
876
|
+
return;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
String kind = track.kind();
|
|
880
|
+
if ("audio".equals(kind)) {
|
|
881
|
+
stream.removeTrack((AudioTrack) track);
|
|
882
|
+
} else if ("video".equals(kind)) {
|
|
883
|
+
stream.removeTrack((VideoTrack) track);
|
|
884
|
+
}
|
|
885
|
+
});
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
@ReactMethod
|
|
889
|
+
public void mediaStreamRelease(String id) {
|
|
890
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
891
|
+
MediaStream stream = localStreams.get(id);
|
|
892
|
+
if (stream == null) {
|
|
893
|
+
Log.d(TAG, "mediaStreamRelease() stream is null");
|
|
894
|
+
return;
|
|
895
|
+
}
|
|
896
|
+
localStreams.remove(id);
|
|
897
|
+
stream.dispose();
|
|
898
|
+
});
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
@ReactMethod
|
|
902
|
+
public void mediaStreamTrackRelease(String id) {
|
|
903
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
904
|
+
MediaStreamTrack track = getLocalTrack(id);
|
|
905
|
+
if (track == null) {
|
|
906
|
+
Log.d(TAG, "mediaStreamTrackRelease() track is null");
|
|
907
|
+
return;
|
|
908
|
+
}
|
|
909
|
+
track.setEnabled(false);
|
|
910
|
+
getUserMediaImpl.disposeTrack(id);
|
|
911
|
+
});
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
@ReactMethod
|
|
915
|
+
public void mediaStreamTrackSetEnabled(int pcId, String id, boolean enabled) {
|
|
916
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
917
|
+
MediaStreamTrack track = getTrack(pcId, id);
|
|
918
|
+
if (track == null) {
|
|
919
|
+
Log.d(TAG, "mediaStreamTrackSetEnabled() could not find track " + id);
|
|
920
|
+
return;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
if (track.enabled() == enabled) {
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
926
|
+
track.setEnabled(enabled);
|
|
927
|
+
getUserMediaImpl.mediaStreamTrackSetEnabled(id, enabled);
|
|
928
|
+
});
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
@ReactMethod
|
|
932
|
+
public void mediaStreamTrackApplyConstraints(String id, ReadableMap constraints, Promise promise) {
|
|
933
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
934
|
+
MediaStreamTrack track = getLocalTrack(id);
|
|
935
|
+
if (track != null) {
|
|
936
|
+
getUserMediaImpl.applyConstraints(id, constraints, promise);
|
|
937
|
+
} else {
|
|
938
|
+
promise.reject(new Exception("mediaStreamTrackApplyConstraints() could not find track " + id));
|
|
939
|
+
}
|
|
940
|
+
});
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
@ReactMethod
|
|
944
|
+
public void mediaStreamTrackSetVolume(int pcId, String id, double volume) {
|
|
945
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
946
|
+
MediaStreamTrack track = getTrack(pcId, id);
|
|
947
|
+
if (track == null) {
|
|
948
|
+
Log.d(TAG, "mediaStreamTrackSetVolume() could not find track " + id);
|
|
949
|
+
return;
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
if (!(track instanceof AudioTrack)) {
|
|
953
|
+
Log.d(TAG, "mediaStreamTrackSetVolume() track is not an AudioTrack!");
|
|
954
|
+
return;
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
((AudioTrack) track).setVolume(volume);
|
|
958
|
+
});
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
/**
|
|
962
|
+
* This serializes the transceivers current direction and mid and returns them
|
|
963
|
+
* for update when an sdp negotiation/renegotiation happens
|
|
964
|
+
*/
|
|
965
|
+
private ReadableArray getTransceiversInfo(PeerConnection peerConnection) {
|
|
966
|
+
WritableArray transceiverUpdates = Arguments.createArray();
|
|
967
|
+
|
|
968
|
+
for (RtpTransceiver transceiver : peerConnection.getTransceivers()) {
|
|
969
|
+
WritableMap transceiverUpdate = Arguments.createMap();
|
|
970
|
+
|
|
971
|
+
RtpTransceiver.RtpTransceiverDirection direction = transceiver.getCurrentDirection();
|
|
972
|
+
if (direction != null) {
|
|
973
|
+
String directionSerialized = SerializeUtils.serializeDirection(direction);
|
|
974
|
+
transceiverUpdate.putString("currentDirection", directionSerialized);
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
transceiverUpdate.putString("transceiverId", transceiver.getSender().id());
|
|
978
|
+
transceiverUpdate.putString("mid", transceiver.getMid());
|
|
979
|
+
transceiverUpdate.putBoolean("isStopped", transceiver.isStopped());
|
|
980
|
+
transceiverUpdate.putMap("senderRtpParameters",
|
|
981
|
+
SerializeUtils.serializeRtpParameters(transceiver.getSender().getParameters()));
|
|
982
|
+
transceiverUpdate.putMap("receiverRtpParameters",
|
|
983
|
+
SerializeUtils.serializeRtpParameters(transceiver.getReceiver().getParameters()));
|
|
984
|
+
transceiverUpdates.pushMap(transceiverUpdate);
|
|
985
|
+
}
|
|
986
|
+
return transceiverUpdates;
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
@ReactMethod
|
|
990
|
+
public void mediaStreamTrackSetVideoEffects(String id, ReadableArray names) {
|
|
991
|
+
ThreadUtils.runOnExecutor(() -> { getUserMediaImpl.setVideoEffects(id, names); });
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
@ReactMethod
|
|
995
|
+
public void peerConnectionSetConfiguration(ReadableMap configuration, int id) {
|
|
996
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
997
|
+
PeerConnection peerConnection = getPeerConnection(id);
|
|
998
|
+
if (peerConnection == null) {
|
|
999
|
+
Log.d(TAG, "peerConnectionSetConfiguration() peerConnection is null");
|
|
1000
|
+
return;
|
|
1001
|
+
}
|
|
1002
|
+
peerConnection.setConfiguration(parseRTCConfiguration(configuration));
|
|
1003
|
+
});
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
@ReactMethod
|
|
1007
|
+
public void peerConnectionCreateOffer(int id, ReadableMap options, Promise promise) {
|
|
1008
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1009
|
+
PeerConnectionObserver pco = mPeerConnectionObservers.get(id);
|
|
1010
|
+
PeerConnection peerConnection = pco.getPeerConnection();
|
|
1011
|
+
|
|
1012
|
+
if (peerConnection == null) {
|
|
1013
|
+
Log.d(TAG, "peerConnectionCreateOffer() peerConnection is null");
|
|
1014
|
+
promise.reject(new Exception("PeerConnection not found"));
|
|
1015
|
+
return;
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
List<String> receiversIds = new ArrayList<>();
|
|
1019
|
+
for (RtpTransceiver transceiver : peerConnection.getTransceivers()) {
|
|
1020
|
+
receiversIds.add(transceiver.getReceiver().id());
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
final SdpObserver observer = new SdpObserver() {
|
|
1024
|
+
@Override
|
|
1025
|
+
public void onCreateFailure(String s) {
|
|
1026
|
+
ThreadUtils.runOnExecutor(() -> { promise.reject("E_OPERATION_ERROR", s); });
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
@Override
|
|
1030
|
+
public void onCreateSuccess(SessionDescription sdp) {
|
|
1031
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1032
|
+
WritableMap params = Arguments.createMap();
|
|
1033
|
+
WritableMap sdpInfo = Arguments.createMap();
|
|
1034
|
+
|
|
1035
|
+
sdpInfo.putString("sdp", sdp.description);
|
|
1036
|
+
sdpInfo.putString("type", sdp.type.canonicalForm());
|
|
1037
|
+
|
|
1038
|
+
params.putArray("transceiversInfo", getTransceiversInfo(peerConnection));
|
|
1039
|
+
params.putMap("sdpInfo", sdpInfo);
|
|
1040
|
+
|
|
1041
|
+
WritableArray newTransceivers = Arguments.createArray();
|
|
1042
|
+
for (RtpTransceiver transceiver : peerConnection.getTransceivers()) {
|
|
1043
|
+
if (!receiversIds.contains(transceiver.getReceiver().id())) {
|
|
1044
|
+
WritableMap newTransceiver = Arguments.createMap();
|
|
1045
|
+
newTransceiver.putInt("transceiverOrder", pco.getNextTransceiverId());
|
|
1046
|
+
newTransceiver.putMap(
|
|
1047
|
+
"transceiver", SerializeUtils.serializeTransceiver(id, transceiver));
|
|
1048
|
+
newTransceivers.pushMap(newTransceiver);
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
params.putArray("newTransceivers", newTransceivers);
|
|
1053
|
+
|
|
1054
|
+
promise.resolve(params);
|
|
1055
|
+
});
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
@Override
|
|
1059
|
+
public void onSetFailure(String s) {}
|
|
1060
|
+
|
|
1061
|
+
@Override
|
|
1062
|
+
public void onSetSuccess() {}
|
|
1063
|
+
};
|
|
1064
|
+
|
|
1065
|
+
peerConnection.createOffer(observer, constraintsForOptions(options));
|
|
1066
|
+
});
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
@ReactMethod
|
|
1070
|
+
public void peerConnectionCreateAnswer(int id, ReadableMap options, Promise promise) {
|
|
1071
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1072
|
+
PeerConnection peerConnection = getPeerConnection(id);
|
|
1073
|
+
|
|
1074
|
+
if (peerConnection == null) {
|
|
1075
|
+
Log.d(TAG, "peerConnectionCreateAnswer() peerConnection is null");
|
|
1076
|
+
promise.reject(new Exception("PeerConnection not found"));
|
|
1077
|
+
return;
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
final SdpObserver observer = new SdpObserver() {
|
|
1081
|
+
@Override
|
|
1082
|
+
public void onCreateFailure(String s) {
|
|
1083
|
+
ThreadUtils.runOnExecutor(() -> { promise.reject("E_OPERATION_ERROR", s); });
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
@Override
|
|
1087
|
+
public void onCreateSuccess(SessionDescription sdp) {
|
|
1088
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1089
|
+
WritableMap params = Arguments.createMap();
|
|
1090
|
+
WritableMap sdpInfo = Arguments.createMap();
|
|
1091
|
+
|
|
1092
|
+
sdpInfo.putString("sdp", sdp.description);
|
|
1093
|
+
sdpInfo.putString("type", sdp.type.canonicalForm());
|
|
1094
|
+
|
|
1095
|
+
params.putArray("transceiversInfo", getTransceiversInfo(peerConnection));
|
|
1096
|
+
params.putMap("sdpInfo", sdpInfo);
|
|
1097
|
+
|
|
1098
|
+
promise.resolve(params);
|
|
1099
|
+
});
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
@Override
|
|
1103
|
+
public void onSetFailure(String s) {}
|
|
1104
|
+
|
|
1105
|
+
@Override
|
|
1106
|
+
public void onSetSuccess() {}
|
|
1107
|
+
};
|
|
1108
|
+
|
|
1109
|
+
peerConnection.createAnswer(observer, constraintsForOptions(options));
|
|
1110
|
+
});
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
@ReactMethod
|
|
1114
|
+
public void peerConnectionSetLocalDescription(int pcId, ReadableMap desc, Promise promise) {
|
|
1115
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1116
|
+
PeerConnection peerConnection = getPeerConnection(pcId);
|
|
1117
|
+
if (peerConnection == null) {
|
|
1118
|
+
Log.d(TAG, "peerConnectionSetLocalDescription() peerConnection is null");
|
|
1119
|
+
promise.reject(new Exception("PeerConnection not found"));
|
|
1120
|
+
return;
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
final SdpObserver observer = new SdpObserver() {
|
|
1124
|
+
@Override
|
|
1125
|
+
public void onCreateSuccess(SessionDescription sdp) {}
|
|
1126
|
+
|
|
1127
|
+
@Override
|
|
1128
|
+
public void onSetSuccess() {
|
|
1129
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1130
|
+
WritableMap newSdpMap = Arguments.createMap();
|
|
1131
|
+
WritableMap params = Arguments.createMap();
|
|
1132
|
+
|
|
1133
|
+
SessionDescription newSdp = peerConnection.getLocalDescription();
|
|
1134
|
+
// Can happen when doing a rollback.
|
|
1135
|
+
if (newSdp != null) {
|
|
1136
|
+
newSdpMap.putString("type", newSdp.type.canonicalForm());
|
|
1137
|
+
newSdpMap.putString("sdp", newSdp.description);
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
params.putMap("sdpInfo", newSdpMap);
|
|
1141
|
+
params.putArray("transceiversInfo", getTransceiversInfo(peerConnection));
|
|
1142
|
+
|
|
1143
|
+
promise.resolve(params);
|
|
1144
|
+
});
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
@Override
|
|
1148
|
+
public void onCreateFailure(String s) {}
|
|
1149
|
+
|
|
1150
|
+
@Override
|
|
1151
|
+
public void onSetFailure(String s) {
|
|
1152
|
+
ThreadUtils.runOnExecutor(() -> { promise.reject("E_OPERATION_ERROR", s); });
|
|
1153
|
+
}
|
|
1154
|
+
};
|
|
1155
|
+
|
|
1156
|
+
if (desc != null) {
|
|
1157
|
+
SessionDescription sdp = new SessionDescription(
|
|
1158
|
+
SessionDescription.Type.fromCanonicalForm(Objects.requireNonNull(desc.getString("type"))),
|
|
1159
|
+
desc.getString("sdp"));
|
|
1160
|
+
|
|
1161
|
+
peerConnection.setLocalDescription(observer, sdp);
|
|
1162
|
+
} else {
|
|
1163
|
+
peerConnection.setLocalDescription(observer);
|
|
1164
|
+
}
|
|
1165
|
+
});
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
@ReactMethod
|
|
1169
|
+
public void peerConnectionSetRemoteDescription(int id, ReadableMap desc, Promise promise) {
|
|
1170
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1171
|
+
PeerConnectionObserver pco = mPeerConnectionObservers.get(id);
|
|
1172
|
+
PeerConnection peerConnection = pco.getPeerConnection();
|
|
1173
|
+
|
|
1174
|
+
if (peerConnection == null) {
|
|
1175
|
+
Log.d(TAG, "peerConnectionSetRemoteDescription() peerConnection is null");
|
|
1176
|
+
promise.reject(new Exception("PeerConnection not found"));
|
|
1177
|
+
return;
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
SessionDescription sdp = new SessionDescription(
|
|
1181
|
+
SessionDescription.Type.fromCanonicalForm(desc.getString("type")), desc.getString("sdp"));
|
|
1182
|
+
|
|
1183
|
+
List<String> receiversIds = new ArrayList<>();
|
|
1184
|
+
for (RtpTransceiver transceiver : peerConnection.getTransceivers()) {
|
|
1185
|
+
receiversIds.add(transceiver.getReceiver().id());
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
final SdpObserver observer = new SdpObserver() {
|
|
1189
|
+
@Override
|
|
1190
|
+
public void onCreateSuccess(final SessionDescription sdp) {}
|
|
1191
|
+
|
|
1192
|
+
@Override
|
|
1193
|
+
public void onSetSuccess() {
|
|
1194
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1195
|
+
WritableMap newSdpMap = Arguments.createMap();
|
|
1196
|
+
WritableMap params = Arguments.createMap();
|
|
1197
|
+
|
|
1198
|
+
SessionDescription newSdp = peerConnection.getRemoteDescription();
|
|
1199
|
+
// Be defensive for the rollback cases.
|
|
1200
|
+
if (newSdp != null) {
|
|
1201
|
+
newSdpMap.putString("type", newSdp.type.canonicalForm());
|
|
1202
|
+
newSdpMap.putString("sdp", newSdp.description);
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
params.putArray("transceiversInfo", getTransceiversInfo(peerConnection));
|
|
1206
|
+
params.putMap("sdpInfo", newSdpMap);
|
|
1207
|
+
|
|
1208
|
+
WritableArray newTransceivers = Arguments.createArray();
|
|
1209
|
+
for (RtpTransceiver transceiver : peerConnection.getTransceivers()) {
|
|
1210
|
+
if (!receiversIds.contains(transceiver.getReceiver().id())) {
|
|
1211
|
+
WritableMap newTransceiver = Arguments.createMap();
|
|
1212
|
+
newTransceiver.putInt("transceiverOrder", pco.getNextTransceiverId());
|
|
1213
|
+
newTransceiver.putMap(
|
|
1214
|
+
"transceiver", SerializeUtils.serializeTransceiver(id, transceiver));
|
|
1215
|
+
newTransceivers.pushMap(newTransceiver);
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
params.putArray("newTransceivers", newTransceivers);
|
|
1220
|
+
|
|
1221
|
+
promise.resolve(params);
|
|
1222
|
+
});
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
@Override
|
|
1226
|
+
public void onCreateFailure(String s) {}
|
|
1227
|
+
|
|
1228
|
+
@Override
|
|
1229
|
+
public void onSetFailure(String s) {
|
|
1230
|
+
ThreadUtils.runOnExecutor(() -> { promise.reject("E_OPERATION_ERROR", s); });
|
|
1231
|
+
}
|
|
1232
|
+
};
|
|
1233
|
+
|
|
1234
|
+
peerConnection.setRemoteDescription(observer, sdp);
|
|
1235
|
+
});
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
1239
|
+
public WritableMap receiverGetCapabilities(String kind) {
|
|
1240
|
+
try {
|
|
1241
|
+
return (WritableMap) ThreadUtils
|
|
1242
|
+
.submitToExecutor((Callable<Object>) () -> {
|
|
1243
|
+
MediaStreamTrack.MediaType mediaType;
|
|
1244
|
+
if (kind.equals("audio")) {
|
|
1245
|
+
mediaType = MediaStreamTrack.MediaType.MEDIA_TYPE_AUDIO;
|
|
1246
|
+
} else if (kind.equals("video")) {
|
|
1247
|
+
mediaType = MediaStreamTrack.MediaType.MEDIA_TYPE_VIDEO;
|
|
1248
|
+
} else {
|
|
1249
|
+
return Arguments.createMap();
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
RtpCapabilities capabilities = mFactory.getRtpReceiverCapabilities(mediaType);
|
|
1253
|
+
return SerializeUtils.serializeRtpCapabilities(capabilities);
|
|
1254
|
+
})
|
|
1255
|
+
.get();
|
|
1256
|
+
} catch (ExecutionException | InterruptedException e) {
|
|
1257
|
+
Log.d(TAG, "receiverGetCapabilities() " + e.getMessage());
|
|
1258
|
+
return null;
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
1263
|
+
public WritableMap senderGetCapabilities(String kind) {
|
|
1264
|
+
try {
|
|
1265
|
+
return (WritableMap) ThreadUtils
|
|
1266
|
+
.submitToExecutor((Callable<Object>) () -> {
|
|
1267
|
+
MediaStreamTrack.MediaType mediaType;
|
|
1268
|
+
if (kind.equals("audio")) {
|
|
1269
|
+
mediaType = MediaStreamTrack.MediaType.MEDIA_TYPE_AUDIO;
|
|
1270
|
+
} else if (kind.equals("video")) {
|
|
1271
|
+
mediaType = MediaStreamTrack.MediaType.MEDIA_TYPE_VIDEO;
|
|
1272
|
+
} else {
|
|
1273
|
+
return Arguments.createMap();
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
RtpCapabilities capabilities = mFactory.getRtpSenderCapabilities(mediaType);
|
|
1277
|
+
return SerializeUtils.serializeRtpCapabilities(capabilities);
|
|
1278
|
+
})
|
|
1279
|
+
.get();
|
|
1280
|
+
} catch (ExecutionException | InterruptedException e) {
|
|
1281
|
+
Log.d(TAG, "senderGetCapabilities() " + e.getMessage());
|
|
1282
|
+
return null;
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
@ReactMethod
|
|
1287
|
+
public void receiverGetStats(int pcId, String receiverId, Promise promise) {
|
|
1288
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1289
|
+
PeerConnectionObserver pco = mPeerConnectionObservers.get(pcId);
|
|
1290
|
+
if (pco == null || pco.getPeerConnection() == null) {
|
|
1291
|
+
Log.d(TAG, "receiverGetStats() peerConnection is null");
|
|
1292
|
+
promise.resolve(StringUtils.statsToJSON(new RTCStatsReport(0, new HashMap<>())));
|
|
1293
|
+
} else {
|
|
1294
|
+
pco.receiverGetStats(receiverId, promise);
|
|
1295
|
+
}
|
|
1296
|
+
});
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
@ReactMethod
|
|
1300
|
+
public void senderGetStats(int pcId, String senderId, Promise promise) {
|
|
1301
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1302
|
+
PeerConnectionObserver pco = mPeerConnectionObservers.get(pcId);
|
|
1303
|
+
if (pco == null || pco.getPeerConnection() == null) {
|
|
1304
|
+
Log.d(TAG, "senderGetStats() peerConnection is null");
|
|
1305
|
+
promise.resolve(StringUtils.statsToJSON(new RTCStatsReport(0, new HashMap<>())));
|
|
1306
|
+
} else {
|
|
1307
|
+
pco.senderGetStats(senderId, promise);
|
|
1308
|
+
}
|
|
1309
|
+
});
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
@ReactMethod
|
|
1313
|
+
public void peerConnectionAddICECandidate(int pcId, ReadableMap candidateMap, Promise promise) {
|
|
1314
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1315
|
+
PeerConnection peerConnection = getPeerConnection(pcId);
|
|
1316
|
+
if (peerConnection == null) {
|
|
1317
|
+
Log.d(TAG, "peerConnectionAddICECandidate() peerConnection is null");
|
|
1318
|
+
promise.reject(new Exception("PeerConnection not found"));
|
|
1319
|
+
return;
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
if (!candidateMap.hasKey("sdpMid") && !candidateMap.hasKey("sdpMLineIndex")) {
|
|
1323
|
+
promise.reject("E_TYPE_ERROR", "Invalid argument");
|
|
1324
|
+
return;
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
IceCandidate candidate = new IceCandidate(candidateMap.hasKey("sdpMid") && !candidateMap.isNull("sdpMid")
|
|
1328
|
+
? candidateMap.getString("sdpMid")
|
|
1329
|
+
: "",
|
|
1330
|
+
candidateMap.hasKey("sdpMLineIndex") && !candidateMap.isNull("sdpMLineIndex")
|
|
1331
|
+
? candidateMap.getInt("sdpMLineIndex")
|
|
1332
|
+
: 0,
|
|
1333
|
+
candidateMap.getString("candidate"));
|
|
1334
|
+
|
|
1335
|
+
peerConnection.addIceCandidate(candidate, new AddIceObserver() {
|
|
1336
|
+
@Override
|
|
1337
|
+
public void onAddSuccess() {
|
|
1338
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1339
|
+
WritableMap newSdpMap = Arguments.createMap();
|
|
1340
|
+
SessionDescription newSdp = peerConnection.getRemoteDescription();
|
|
1341
|
+
newSdpMap.putString("type", newSdp.type.canonicalForm());
|
|
1342
|
+
newSdpMap.putString("sdp", newSdp.description);
|
|
1343
|
+
promise.resolve(newSdpMap);
|
|
1344
|
+
});
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
@Override
|
|
1348
|
+
public void onAddFailure(String s) {
|
|
1349
|
+
ThreadUtils.runOnExecutor(() -> { promise.reject("E_OPERATION_ERROR", s); });
|
|
1350
|
+
}
|
|
1351
|
+
});
|
|
1352
|
+
});
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
@ReactMethod
|
|
1356
|
+
public void peerConnectionGetStats(int peerConnectionId, Promise promise) {
|
|
1357
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1358
|
+
PeerConnectionObserver pco = mPeerConnectionObservers.get(peerConnectionId);
|
|
1359
|
+
if (pco == null || pco.getPeerConnection() == null) {
|
|
1360
|
+
Log.d(TAG, "peerConnectionGetStats() peerConnection is null");
|
|
1361
|
+
promise.resolve(StringUtils.statsToJSON(new RTCStatsReport(0, new HashMap<>())));
|
|
1362
|
+
} else {
|
|
1363
|
+
pco.getStats(promise);
|
|
1364
|
+
}
|
|
1365
|
+
});
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
@ReactMethod
|
|
1369
|
+
public void peerConnectionClose(int id) {
|
|
1370
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1371
|
+
PeerConnectionObserver pco = mPeerConnectionObservers.get(id);
|
|
1372
|
+
if (pco == null || pco.getPeerConnection() == null) {
|
|
1373
|
+
Log.d(TAG, "peerConnectionClose() peerConnection is null");
|
|
1374
|
+
return;
|
|
1375
|
+
}
|
|
1376
|
+
pco.close();
|
|
1377
|
+
});
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
@ReactMethod
|
|
1381
|
+
public void peerConnectionDispose(int id) {
|
|
1382
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1383
|
+
PeerConnectionObserver pco = mPeerConnectionObservers.get(id);
|
|
1384
|
+
if (pco == null || pco.getPeerConnection() == null) {
|
|
1385
|
+
Log.d(TAG, "peerConnectionDispose() peerConnection is null");
|
|
1386
|
+
}
|
|
1387
|
+
pco.dispose();
|
|
1388
|
+
mPeerConnectionObservers.remove(id);
|
|
1389
|
+
});
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
@ReactMethod
|
|
1393
|
+
public void peerConnectionRestartIce(int pcId) {
|
|
1394
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1395
|
+
PeerConnection peerConnection = getPeerConnection(pcId);
|
|
1396
|
+
if (peerConnection == null) {
|
|
1397
|
+
Log.w(TAG, "peerConnectionRestartIce() peerConnection is null");
|
|
1398
|
+
return;
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
peerConnection.restartIce();
|
|
1402
|
+
});
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
1406
|
+
public WritableMap createDataChannel(int peerConnectionId, String label, ReadableMap config) {
|
|
1407
|
+
try {
|
|
1408
|
+
return (WritableMap) ThreadUtils
|
|
1409
|
+
.submitToExecutor((Callable<Object>) () -> {
|
|
1410
|
+
PeerConnectionObserver pco = mPeerConnectionObservers.get(peerConnectionId);
|
|
1411
|
+
if (pco == null || pco.getPeerConnection() == null) {
|
|
1412
|
+
Log.d(TAG, "createDataChannel() peerConnection is null");
|
|
1413
|
+
return null;
|
|
1414
|
+
} else {
|
|
1415
|
+
return pco.createDataChannel(label, config);
|
|
1416
|
+
}
|
|
1417
|
+
})
|
|
1418
|
+
.get();
|
|
1419
|
+
} catch (ExecutionException | InterruptedException e) {
|
|
1420
|
+
return null;
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
@ReactMethod
|
|
1425
|
+
public void dataChannelClose(int peerConnectionId, String reactTag) {
|
|
1426
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1427
|
+
// Forward to PeerConnectionObserver which deals with DataChannels
|
|
1428
|
+
// because DataChannel is owned by PeerConnection.
|
|
1429
|
+
PeerConnectionObserver pco = mPeerConnectionObservers.get(peerConnectionId);
|
|
1430
|
+
if (pco == null || pco.getPeerConnection() == null) {
|
|
1431
|
+
Log.d(TAG, "dataChannelClose() peerConnection is null");
|
|
1432
|
+
return;
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
pco.dataChannelClose(reactTag);
|
|
1436
|
+
});
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
@ReactMethod
|
|
1440
|
+
public void dataChannelDispose(int peerConnectionId, String reactTag) {
|
|
1441
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1442
|
+
PeerConnectionObserver pco = mPeerConnectionObservers.get(peerConnectionId);
|
|
1443
|
+
if (pco == null || pco.getPeerConnection() == null) {
|
|
1444
|
+
Log.d(TAG, "dataChannelDispose() peerConnection is null");
|
|
1445
|
+
return;
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1448
|
+
pco.dataChannelDispose(reactTag);
|
|
1449
|
+
});
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
@ReactMethod
|
|
1453
|
+
public void dataChannelSend(int peerConnectionId, String reactTag, String data, String type) {
|
|
1454
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1455
|
+
// Forward to PeerConnectionObserver which deals with DataChannels
|
|
1456
|
+
// because DataChannel is owned by PeerConnection.
|
|
1457
|
+
PeerConnectionObserver pco = mPeerConnectionObservers.get(peerConnectionId);
|
|
1458
|
+
if (pco == null || pco.getPeerConnection() == null) {
|
|
1459
|
+
Log.d(TAG, "dataChannelSend() peerConnection is null");
|
|
1460
|
+
return;
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
pco.dataChannelSend(reactTag, data, type);
|
|
1464
|
+
});
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
// Frame Cryptor methods
|
|
1468
|
+
////////////////////////////////
|
|
1469
|
+
RTCCryptoManager frameCryptor = new RTCCryptoManager(this);
|
|
1470
|
+
|
|
1471
|
+
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
1472
|
+
public String frameCryptorFactoryCreateFrameCryptor(ReadableMap config) {
|
|
1473
|
+
return frameCryptor.frameCryptorFactoryCreateFrameCryptor(config);
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1476
|
+
@ReactMethod
|
|
1477
|
+
public void frameCryptorSetKeyIndex(ReadableMap config, Promise promise) {
|
|
1478
|
+
frameCryptor.frameCryptorSetKeyIndex(config, promise);
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
@ReactMethod
|
|
1482
|
+
public void frameCryptorGetKeyIndex(ReadableMap config, Promise promise) {
|
|
1483
|
+
frameCryptor.frameCryptorGetKeyIndex(config, promise);
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
@ReactMethod
|
|
1487
|
+
public void frameCryptorSetEnabled(ReadableMap config, Promise promise) {
|
|
1488
|
+
frameCryptor.frameCryptorSetEnabled(config, promise);
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1491
|
+
@ReactMethod
|
|
1492
|
+
public void frameCryptorGetEnabled(ReadableMap config, Promise promise) {
|
|
1493
|
+
frameCryptor.frameCryptorGetEnabled(config, promise);
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
@ReactMethod
|
|
1497
|
+
public void frameCryptorDispose(ReadableMap config, Promise promise) {
|
|
1498
|
+
frameCryptor.frameCryptorDispose(config, promise);
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
1502
|
+
public String frameCryptorFactoryCreateKeyProvider(ReadableMap config) {
|
|
1503
|
+
return frameCryptor.frameCryptorFactoryCreateKeyProvider(config);
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
@ReactMethod
|
|
1507
|
+
public void keyProviderSetSharedKey(ReadableMap config, Promise promise) {
|
|
1508
|
+
frameCryptor.keyProviderSetSharedKey(config, promise);
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
@ReactMethod
|
|
1512
|
+
public void keyProviderRatchetSharedKey(ReadableMap config, Promise promise) {
|
|
1513
|
+
frameCryptor.keyProviderRatchetSharedKey(config, promise);
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
@ReactMethod
|
|
1517
|
+
public void keyProviderExportSharedKey(ReadableMap config, Promise promise) {
|
|
1518
|
+
frameCryptor.keyProviderExportSharedKey(config, promise);
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1521
|
+
@ReactMethod
|
|
1522
|
+
public void keyProviderSetKey(ReadableMap config, Promise promise) {
|
|
1523
|
+
frameCryptor.keyProviderSetKey(config, promise);
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
@ReactMethod
|
|
1527
|
+
public void keyProviderRatchetKey(ReadableMap config, Promise promise) {
|
|
1528
|
+
frameCryptor.keyProviderRatchetKey(config, promise);
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1531
|
+
@ReactMethod
|
|
1532
|
+
public void keyProviderExportKey(ReadableMap config, Promise promise) {
|
|
1533
|
+
frameCryptor.keyProviderExportKey(config, promise);
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
@ReactMethod
|
|
1537
|
+
public void keyProviderSetSifTrailer(ReadableMap config, Promise promise) {
|
|
1538
|
+
frameCryptor.keyProviderSetSifTrailer(config, promise);
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
@ReactMethod
|
|
1542
|
+
public void keyProviderDispose(ReadableMap config, Promise promise) {
|
|
1543
|
+
frameCryptor.keyProviderDispose(config, promise);
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
@ReactMethod
|
|
1547
|
+
public void dataPacketCryptorFactoryCreateDataPacketCryptor(ReadableMap params, @NonNull Promise result) {
|
|
1548
|
+
frameCryptor.dataPacketCryptorFactoryCreateDataPacketCryptor(params, result);
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1551
|
+
@ReactMethod
|
|
1552
|
+
public void dataPacketCryptorEncrypt(ReadableMap params, @NonNull Promise result) {
|
|
1553
|
+
frameCryptor.dataPacketCryptorEncrypt(params, result);
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1556
|
+
@ReactMethod
|
|
1557
|
+
public void dataPacketCryptorDecrypt(ReadableMap params, @NonNull Promise result) {
|
|
1558
|
+
frameCryptor.dataPacketCryptorDecrypt(params, result);
|
|
1559
|
+
}
|
|
1560
|
+
|
|
1561
|
+
@ReactMethod
|
|
1562
|
+
public void dataPacketCryptorDispose(ReadableMap params, @NonNull Promise result) {
|
|
1563
|
+
frameCryptor.dataPacketCryptorDispose(params, result);
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1566
|
+
@ReactMethod
|
|
1567
|
+
public void addListener(String eventName) {
|
|
1568
|
+
// Keep: Required for RN built in Event Emitter Calls.
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
@ReactMethod
|
|
1572
|
+
public void removeListeners(Integer count) {
|
|
1573
|
+
// Keep: Required for RN built in Event Emitter Calls.
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
@ReactMethod
|
|
1577
|
+
public void startPalabraTranslation(int peerConnectionId, String trackId, String clientId,
|
|
1578
|
+
String clientSecret, String sourceLang, String targetLang,
|
|
1579
|
+
String apiUrl, Promise promise) {
|
|
1580
|
+
PeerConnectionObserver pco = mPeerConnectionObservers.get(peerConnectionId);
|
|
1581
|
+
if (pco == null) {
|
|
1582
|
+
promise.reject("E_INVALID", "pc_not_found");
|
|
1583
|
+
return;
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
MediaStreamTrack track = pco.remoteTracks.get(trackId);
|
|
1587
|
+
if (track == null) {
|
|
1588
|
+
promise.reject("E_INVALID", "track_not_found");
|
|
1589
|
+
return;
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
if (!(track instanceof AudioTrack)) {
|
|
1593
|
+
promise.reject("E_INVALID", "not_audio_track");
|
|
1594
|
+
return;
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
AudioTrack audioTrack = (AudioTrack) track;
|
|
1598
|
+
|
|
1599
|
+
if (palabraClient != null) {
|
|
1600
|
+
palabraClient.stop();
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
PalabraConfig config = new PalabraConfig(clientId, clientSecret, sourceLang, targetLang, apiUrl);
|
|
1604
|
+
palabraClient = new PalabraClient(getReactApplicationContext(), config);
|
|
1605
|
+
palabraClient.setListener(new PalabraListener() {
|
|
1606
|
+
@Override
|
|
1607
|
+
public void onTranscription(String text, String lang, boolean isFinal) {
|
|
1608
|
+
WritableMap params = Arguments.createMap();
|
|
1609
|
+
params.putString("text", text);
|
|
1610
|
+
params.putString("lang", lang);
|
|
1611
|
+
params.putBoolean("isFinal", isFinal);
|
|
1612
|
+
sendEvent("palabraTranscription", params);
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
@Override
|
|
1616
|
+
public void onConnectionState(String state) {
|
|
1617
|
+
WritableMap params = Arguments.createMap();
|
|
1618
|
+
params.putString("state", state);
|
|
1619
|
+
sendEvent("palabraConnectionState", params);
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
@Override
|
|
1623
|
+
public void onError(int code, String message) {
|
|
1624
|
+
WritableMap params = Arguments.createMap();
|
|
1625
|
+
params.putInt("code", code);
|
|
1626
|
+
params.putString("message", message);
|
|
1627
|
+
sendEvent("palabraError", params);
|
|
1628
|
+
}
|
|
1629
|
+
});
|
|
1630
|
+
|
|
1631
|
+
palabraClient.start(audioTrack);
|
|
1632
|
+
promise.resolve(null);
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
@ReactMethod
|
|
1636
|
+
public void stopPalabraTranslation(Promise promise) {
|
|
1637
|
+
if (palabraClient != null) {
|
|
1638
|
+
palabraClient.stop();
|
|
1639
|
+
palabraClient = null;
|
|
1640
|
+
}
|
|
1641
|
+
promise.resolve(null);
|
|
1642
|
+
}
|
|
1643
|
+
}
|