@sbhjt-gr/react-native-webrtc 124.0.0 → 124.0.1
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 -11
- package/.eslintignore +6 -6
- package/.nvmrc +1 -1
- package/ISSUE_TEMPLATE.md +40 -40
- package/LICENSE +22 -22
- package/README.md +103 -103
- package/android/build.gradle +37 -37
- package/android/consumer-rules.pro +3 -3
- package/android/src/main/AndroidManifest.xml +11 -11
- package/android/src/main/java/com/oney/WebRTCModule/AbstractVideoCaptureController.java +113 -113
- package/android/src/main/java/com/oney/WebRTCModule/CameraCaptureController.java +338 -338
- package/android/src/main/java/com/oney/WebRTCModule/CameraEventsHandler.java +49 -49
- package/android/src/main/java/com/oney/WebRTCModule/DataChannelWrapper.java +99 -99
- package/android/src/main/java/com/oney/WebRTCModule/DataPacketCryptorManager.java +62 -62
- package/android/src/main/java/com/oney/WebRTCModule/DisplayUtils.java +16 -16
- package/android/src/main/java/com/oney/WebRTCModule/EglUtils.java +66 -66
- package/android/src/main/java/com/oney/WebRTCModule/GetUserMediaImpl.java +539 -539
- package/android/src/main/java/com/oney/WebRTCModule/LibraryLoader.java +21 -21
- package/android/src/main/java/com/oney/WebRTCModule/MediaProjectionNotification.java +70 -70
- package/android/src/main/java/com/oney/WebRTCModule/MediaProjectionService.java +82 -82
- package/android/src/main/java/com/oney/WebRTCModule/PeerConnectionObserver.java +588 -588
- package/android/src/main/java/com/oney/WebRTCModule/RTCCryptoManager.java +493 -493
- package/android/src/main/java/com/oney/WebRTCModule/RTCVideoViewManager.java +98 -98
- package/android/src/main/java/com/oney/WebRTCModule/ReactBridgeUtil.java +35 -35
- package/android/src/main/java/com/oney/WebRTCModule/ScreenCaptureController.java +94 -94
- package/android/src/main/java/com/oney/WebRTCModule/SerializeUtils.java +342 -342
- package/android/src/main/java/com/oney/WebRTCModule/StringUtils.java +100 -100
- package/android/src/main/java/com/oney/WebRTCModule/ThreadUtils.java +41 -41
- package/android/src/main/java/com/oney/WebRTCModule/TrackCapturerEventsEmitter.java +34 -34
- package/android/src/main/java/com/oney/WebRTCModule/VideoTrackAdapter.java +137 -137
- package/android/src/main/java/com/oney/WebRTCModule/WebRTCModule.java +1643 -1643
- package/android/src/main/java/com/oney/WebRTCModule/WebRTCModuleOptions.java +33 -33
- package/android/src/main/java/com/oney/WebRTCModule/WebRTCModulePackage.java +21 -21
- package/android/src/main/java/com/oney/WebRTCModule/WebRTCView.java +583 -583
- package/android/src/main/java/com/oney/WebRTCModule/palabra/PalabraClient.java +464 -464
- package/android/src/main/java/com/oney/WebRTCModule/palabra/PalabraConfig.java +17 -17
- package/android/src/main/java/com/oney/WebRTCModule/palabra/PalabraListener.java +7 -7
- package/android/src/main/java/com/oney/WebRTCModule/videoEffects/ProcessorProvider.java +38 -38
- package/android/src/main/java/com/oney/WebRTCModule/videoEffects/VideoEffectProcessor.java +59 -59
- package/android/src/main/java/com/oney/WebRTCModule/videoEffects/VideoFrameProcessor.java +19 -19
- package/android/src/main/java/com/oney/WebRTCModule/videoEffects/VideoFrameProcessorFactoryInterface.java +12 -12
- package/android/src/main/java/com/oney/WebRTCModule/webrtcutils/H264AndSoftwareVideoDecoderFactory.java +73 -73
- package/android/src/main/java/com/oney/WebRTCModule/webrtcutils/H264AndSoftwareVideoEncoderFactory.java +73 -73
- package/android/src/main/java/com/oney/WebRTCModule/webrtcutils/SoftwareVideoDecoderFactoryProxy.java +36 -36
- package/android/src/main/java/com/oney/WebRTCModule/webrtcutils/SoftwareVideoEncoderFactoryProxy.java +36 -36
- package/android/src/main/java/org/webrtc/Camera1Helper.java +54 -54
- package/android/src/main/java/org/webrtc/Camera2Helper.java +52 -52
- package/android/src/main/res/values/strings.xml +5 -5
- package/android/src/main/res/values/styles.xml +8 -8
- package/ios/RCTWebRTC/CaptureController.h +18 -18
- package/ios/RCTWebRTC/CaptureController.m +28 -28
- package/ios/RCTWebRTC/CapturerEventsDelegate.h +12 -12
- package/ios/RCTWebRTC/DataChannelWrapper.h +27 -27
- package/ios/RCTWebRTC/DataChannelWrapper.m +42 -42
- package/ios/RCTWebRTC/I420Converter.h +22 -22
- package/ios/RCTWebRTC/I420Converter.m +164 -164
- package/ios/RCTWebRTC/PIPController.h +24 -24
- package/ios/RCTWebRTC/PIPController.m +234 -234
- package/ios/RCTWebRTC/PalabraAudioSink.h +13 -13
- package/ios/RCTWebRTC/PalabraAudioSink.m +18 -18
- package/ios/RCTWebRTC/PalabraClient.h +36 -36
- package/ios/RCTWebRTC/PalabraClient.m +584 -584
- package/ios/RCTWebRTC/RCTConvert+WebRTC.h +16 -16
- package/ios/RCTWebRTC/RCTConvert+WebRTC.m +206 -206
- package/ios/RCTWebRTC/RTCMediaStreamTrack+React.h +10 -10
- package/ios/RCTWebRTC/RTCMediaStreamTrack+React.m +16 -16
- package/ios/RCTWebRTC/RTCVideoViewManager.h +29 -29
- package/ios/RCTWebRTC/RTCVideoViewManager.m +411 -411
- package/ios/RCTWebRTC/SampleBufferVideoCallView.h +12 -12
- package/ios/RCTWebRTC/SampleBufferVideoCallView.m +178 -178
- package/ios/RCTWebRTC/ScreenCaptureController.h +20 -20
- package/ios/RCTWebRTC/ScreenCaptureController.m +82 -82
- package/ios/RCTWebRTC/ScreenCapturePickerViewManager.h +7 -7
- package/ios/RCTWebRTC/ScreenCapturePickerViewManager.m +59 -59
- package/ios/RCTWebRTC/ScreenCapturer.h +19 -19
- package/ios/RCTWebRTC/ScreenCapturer.m +263 -263
- package/ios/RCTWebRTC/SerializeUtils.h +28 -28
- package/ios/RCTWebRTC/SerializeUtils.m +314 -314
- package/ios/RCTWebRTC/SocketConnection.h +13 -13
- package/ios/RCTWebRTC/SocketConnection.m +137 -137
- package/ios/RCTWebRTC/TrackCapturerEventsEmitter.h +14 -14
- package/ios/RCTWebRTC/TrackCapturerEventsEmitter.m +36 -36
- package/ios/RCTWebRTC/VideoCaptureController.h +21 -21
- package/ios/RCTWebRTC/VideoCaptureController.m +328 -328
- package/ios/RCTWebRTC/WebRTCModule+Palabra.h +4 -4
- package/ios/RCTWebRTC/WebRTCModule+Palabra.m +83 -83
- package/ios/RCTWebRTC/WebRTCModule+Permissions.m +75 -75
- package/ios/RCTWebRTC/WebRTCModule+RTCAudioSession.m +20 -20
- package/ios/RCTWebRTC/WebRTCModule+RTCDataChannel.h +14 -14
- package/ios/RCTWebRTC/WebRTCModule+RTCDataChannel.m +165 -165
- package/ios/RCTWebRTC/WebRTCModule+RTCFrameCryptor.m +611 -611
- package/ios/RCTWebRTC/WebRTCModule+RTCMediaStream.h +13 -13
- package/ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m +728 -533
- package/ios/RCTWebRTC/WebRTCModule+RTCPeerConnection.h +24 -24
- package/ios/RCTWebRTC/WebRTCModule+RTCPeerConnection.m +1004 -1004
- package/ios/RCTWebRTC/WebRTCModule+Transceivers.m +267 -267
- package/ios/RCTWebRTC/WebRTCModule+VideoTrackAdapter.h +12 -12
- package/ios/RCTWebRTC/WebRTCModule+VideoTrackAdapter.m +166 -166
- package/ios/RCTWebRTC/WebRTCModule.h +58 -51
- package/ios/RCTWebRTC/WebRTCModule.m +169 -151
- package/ios/RCTWebRTC/WebRTCModuleOptions.h +24 -24
- package/ios/RCTWebRTC/WebRTCModuleOptions.m +31 -31
- package/ios/RCTWebRTC/videoEffects/ProcessorProvider.h +9 -9
- package/ios/RCTWebRTC/videoEffects/ProcessorProvider.m +23 -23
- package/ios/RCTWebRTC/videoEffects/VideoEffectProcessor.h +13 -13
- package/ios/RCTWebRTC/videoEffects/VideoEffectProcessor.m +23 -23
- package/ios/RCTWebRTC/videoEffects/VideoFrameProcessor.h +8 -8
- package/ios/RCTWebRTC.xcodeproj/project.pbxproj +404 -404
- package/ios/RCTWebRTC.xcworkspace/contents.xcworkspacedata +10 -10
- package/lib/commonjs/Constraints.js.map +1 -1
- package/lib/commonjs/EventEmitter.js.map +1 -1
- package/lib/commonjs/Logger.js.map +1 -1
- package/lib/commonjs/MediaDevices.js +17 -17
- package/lib/commonjs/MediaDevices.js.map +1 -1
- package/lib/commonjs/MediaStream.js +19 -19
- package/lib/commonjs/MediaStream.js.map +1 -1
- package/lib/commonjs/MediaStreamError.js.map +1 -1
- package/lib/commonjs/MediaStreamErrorEvent.js.map +1 -1
- package/lib/commonjs/MediaStreamTrack.js +28 -28
- package/lib/commonjs/MediaStreamTrack.js.map +1 -1
- package/lib/commonjs/MediaStreamTrackEvent.js +6 -6
- package/lib/commonjs/MediaStreamTrackEvent.js.map +1 -1
- package/lib/commonjs/MessageEvent.js +7 -7
- package/lib/commonjs/MessageEvent.js.map +1 -1
- package/lib/commonjs/Permissions.js +28 -28
- package/lib/commonjs/Permissions.js.map +1 -1
- package/lib/commonjs/RTCAudioSession.js +4 -4
- package/lib/commonjs/RTCAudioSession.js.map +1 -1
- package/lib/commonjs/RTCDataChannel.js +2 -2
- package/lib/commonjs/RTCDataChannel.js.map +1 -1
- package/lib/commonjs/RTCDataChannelEvent.js +6 -6
- package/lib/commonjs/RTCDataChannelEvent.js.map +1 -1
- package/lib/commonjs/RTCDataPacketCryptor.js.map +1 -1
- package/lib/commonjs/RTCDataPacketCryptorFactory.js.map +1 -1
- package/lib/commonjs/RTCErrorEvent.js +3 -3
- package/lib/commonjs/RTCErrorEvent.js.map +1 -1
- package/lib/commonjs/RTCFrameCryptor.js +8 -8
- package/lib/commonjs/RTCFrameCryptor.js.map +1 -1
- package/lib/commonjs/RTCFrameCryptorFactory.js.map +1 -1
- package/lib/commonjs/RTCIceCandidate.js.map +1 -1
- package/lib/commonjs/RTCIceCandidateEvent.js +7 -7
- package/lib/commonjs/RTCIceCandidateEvent.js.map +1 -1
- package/lib/commonjs/RTCKeyProvider.js.map +1 -1
- package/lib/commonjs/RTCPIPView.js +2 -2
- package/lib/commonjs/RTCPIPView.js.map +1 -1
- package/lib/commonjs/RTCPIPView.web.js.map +1 -1
- package/lib/commonjs/RTCPeerConnection.js +36 -36
- package/lib/commonjs/RTCPeerConnection.js.map +1 -1
- package/lib/commonjs/RTCRtcpParameters.js.map +1 -1
- package/lib/commonjs/RTCRtpCapabilities.js +2 -2
- package/lib/commonjs/RTCRtpCapabilities.js.map +1 -1
- package/lib/commonjs/RTCRtpCodecCapability.js.map +1 -1
- package/lib/commonjs/RTCRtpCodecParameters.js.map +1 -1
- package/lib/commonjs/RTCRtpEncodingParameters.js.map +1 -1
- package/lib/commonjs/RTCRtpHeaderExtension.js.map +1 -1
- package/lib/commonjs/RTCRtpParameters.js.map +1 -1
- package/lib/commonjs/RTCRtpReceiveParameters.js.map +1 -1
- package/lib/commonjs/RTCRtpReceiver.js +7 -7
- package/lib/commonjs/RTCRtpReceiver.js.map +1 -1
- package/lib/commonjs/RTCRtpSendParameters.js +3 -3
- package/lib/commonjs/RTCRtpSendParameters.js.map +1 -1
- package/lib/commonjs/RTCRtpSender.js +7 -7
- package/lib/commonjs/RTCRtpSender.js.map +1 -1
- package/lib/commonjs/RTCRtpTransceiver.js.map +1 -1
- package/lib/commonjs/RTCSessionDescription.js.map +1 -1
- package/lib/commonjs/RTCTrackEvent.js +6 -6
- package/lib/commonjs/RTCTrackEvent.js.map +1 -1
- package/lib/commonjs/RTCUtil.js +28 -28
- package/lib/commonjs/RTCUtil.js.map +1 -1
- package/lib/commonjs/RTCView.js +5 -5
- package/lib/commonjs/RTCView.js.map +1 -1
- package/lib/commonjs/RTCView.web.js.map +1 -1
- package/lib/commonjs/ScreenCapturePickerView.js.map +1 -1
- package/lib/commonjs/ScreenCapturePickerView.web.js.map +1 -1
- package/lib/commonjs/getDisplayMedia.js.map +1 -1
- package/lib/commonjs/getUserMedia.js.map +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.web.js.map +1 -1
- package/lib/commonjs/webStream.js.map +1 -1
- package/lib/module/Constraints.js.map +1 -1
- package/lib/module/EventEmitter.js.map +1 -1
- package/lib/module/Logger.js.map +1 -1
- package/lib/module/MediaDevices.js +17 -17
- package/lib/module/MediaDevices.js.map +1 -1
- package/lib/module/MediaStream.js +19 -19
- package/lib/module/MediaStream.js.map +1 -1
- package/lib/module/MediaStreamError.js.map +1 -1
- package/lib/module/MediaStreamErrorEvent.js.map +1 -1
- package/lib/module/MediaStreamTrack.js +28 -28
- package/lib/module/MediaStreamTrack.js.map +1 -1
- package/lib/module/MediaStreamTrackEvent.js +6 -6
- package/lib/module/MediaStreamTrackEvent.js.map +1 -1
- package/lib/module/MessageEvent.js +7 -7
- package/lib/module/MessageEvent.js.map +1 -1
- package/lib/module/Permissions.js +28 -28
- package/lib/module/Permissions.js.map +1 -1
- package/lib/module/RTCAudioSession.js +4 -4
- package/lib/module/RTCAudioSession.js.map +1 -1
- package/lib/module/RTCDataChannel.js +2 -2
- package/lib/module/RTCDataChannel.js.map +1 -1
- package/lib/module/RTCDataChannelEvent.js +6 -6
- package/lib/module/RTCDataChannelEvent.js.map +1 -1
- package/lib/module/RTCDataPacketCryptor.js.map +1 -1
- package/lib/module/RTCDataPacketCryptorFactory.js.map +1 -1
- package/lib/module/RTCErrorEvent.js +3 -3
- package/lib/module/RTCErrorEvent.js.map +1 -1
- package/lib/module/RTCFrameCryptor.js +8 -8
- package/lib/module/RTCFrameCryptor.js.map +1 -1
- package/lib/module/RTCFrameCryptorFactory.js.map +1 -1
- package/lib/module/RTCIceCandidate.js.map +1 -1
- package/lib/module/RTCIceCandidateEvent.js +7 -7
- package/lib/module/RTCIceCandidateEvent.js.map +1 -1
- package/lib/module/RTCKeyProvider.js.map +1 -1
- package/lib/module/RTCPIPView.js +2 -2
- package/lib/module/RTCPIPView.js.map +1 -1
- package/lib/module/RTCPIPView.web.js.map +1 -1
- package/lib/module/RTCPeerConnection.js +36 -36
- package/lib/module/RTCPeerConnection.js.map +1 -1
- package/lib/module/RTCRtcpParameters.js.map +1 -1
- package/lib/module/RTCRtpCapabilities.js +2 -2
- package/lib/module/RTCRtpCapabilities.js.map +1 -1
- package/lib/module/RTCRtpCodecCapability.js.map +1 -1
- package/lib/module/RTCRtpCodecParameters.js.map +1 -1
- package/lib/module/RTCRtpEncodingParameters.js.map +1 -1
- package/lib/module/RTCRtpHeaderExtension.js.map +1 -1
- package/lib/module/RTCRtpParameters.js.map +1 -1
- package/lib/module/RTCRtpReceiveParameters.js.map +1 -1
- package/lib/module/RTCRtpReceiver.js +7 -7
- package/lib/module/RTCRtpReceiver.js.map +1 -1
- package/lib/module/RTCRtpSendParameters.js +3 -3
- package/lib/module/RTCRtpSendParameters.js.map +1 -1
- package/lib/module/RTCRtpSender.js +7 -7
- package/lib/module/RTCRtpSender.js.map +1 -1
- package/lib/module/RTCRtpTransceiver.js.map +1 -1
- package/lib/module/RTCSessionDescription.js.map +1 -1
- package/lib/module/RTCTrackEvent.js +6 -6
- package/lib/module/RTCTrackEvent.js.map +1 -1
- package/lib/module/RTCUtil.js +28 -28
- package/lib/module/RTCUtil.js.map +1 -1
- package/lib/module/RTCView.js +5 -5
- package/lib/module/RTCView.js.map +1 -1
- package/lib/module/RTCView.web.js.map +1 -1
- package/lib/module/ScreenCapturePickerView.js.map +1 -1
- package/lib/module/ScreenCapturePickerView.web.js.map +1 -1
- package/lib/module/getDisplayMedia.js.map +1 -1
- package/lib/module/getUserMedia.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js.map +1 -1
- package/lib/module/webStream.js.map +1 -1
- package/lib/typescript/Constraints.d.ts +19 -19
- package/lib/typescript/EventEmitter.d.ts +6 -6
- package/lib/typescript/Logger.d.ts +13 -13
- package/lib/typescript/MediaDevices.d.ts +30 -30
- package/lib/typescript/MediaStream.d.ts +48 -48
- package/lib/typescript/MediaStreamError.d.ts +6 -6
- package/lib/typescript/MediaStreamErrorEvent.d.ts +6 -6
- package/lib/typescript/MediaStreamTrack.d.ts +101 -101
- package/lib/typescript/MediaStreamTrackEvent.d.ts +19 -19
- package/lib/typescript/MessageEvent.d.ts +20 -20
- package/lib/typescript/Permissions.d.ts +55 -55
- package/lib/typescript/RTCAudioSession.d.ts +10 -10
- package/lib/typescript/RTCDataChannel.d.ts +43 -43
- package/lib/typescript/RTCDataChannelEvent.d.ts +19 -19
- package/lib/typescript/RTCDataPacketCryptor.d.ts +12 -12
- package/lib/typescript/RTCDataPacketCryptorFactory.d.ts +6 -6
- package/lib/typescript/RTCErrorEvent.d.ts +12 -12
- package/lib/typescript/RTCFrameCryptor.d.ts +47 -47
- package/lib/typescript/RTCFrameCryptorFactory.d.ts +21 -21
- package/lib/typescript/RTCIceCandidate.d.ts +17 -17
- package/lib/typescript/RTCIceCandidateEvent.d.ts +20 -20
- package/lib/typescript/RTCKeyProvider.d.ts +21 -21
- package/lib/typescript/RTCPIPView.d.ts +15 -15
- package/lib/typescript/RTCPIPView.web.d.ts +13 -13
- package/lib/typescript/RTCPeerConnection.d.ts +117 -117
- package/lib/typescript/RTCRtcpParameters.d.ts +10 -10
- package/lib/typescript/RTCRtpCapabilities.d.ts +9 -9
- package/lib/typescript/RTCRtpCodecCapability.d.ts +7 -7
- package/lib/typescript/RTCRtpCodecParameters.d.ts +16 -16
- package/lib/typescript/RTCRtpEncodingParameters.d.ts +23 -23
- package/lib/typescript/RTCRtpHeaderExtension.d.ts +12 -12
- package/lib/typescript/RTCRtpParameters.d.ts +19 -19
- package/lib/typescript/RTCRtpReceiveParameters.d.ts +4 -4
- package/lib/typescript/RTCRtpReceiver.d.ts +21 -21
- package/lib/typescript/RTCRtpSendParameters.d.ts +20 -20
- package/lib/typescript/RTCRtpSender.d.ts +22 -22
- package/lib/typescript/RTCRtpTransceiver.d.ts +31 -31
- package/lib/typescript/RTCSessionDescription.d.ts +12 -12
- package/lib/typescript/RTCTrackEvent.d.ts +29 -29
- package/lib/typescript/RTCUtil.d.ts +37 -37
- package/lib/typescript/RTCView.d.ts +117 -117
- package/lib/typescript/RTCView.web.d.ts +25 -25
- package/lib/typescript/ScreenCapturePickerView.d.ts +2 -2
- package/lib/typescript/ScreenCapturePickerView.web.d.ts +1 -1
- package/lib/typescript/getDisplayMedia.d.ts +2 -2
- package/lib/typescript/getUserMedia.d.ts +7 -7
- package/lib/typescript/index.d.ts +22 -22
- package/lib/typescript/index.web.d.ts +101 -101
- package/lib/typescript/webStream.d.ts +3 -3
- package/livekit-react-native-webrtc.podspec +29 -29
- package/macos/RCTWebRTC.xcodeproj/project.pbxproj +324 -324
- package/macos/RCTWebRTC.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -7
- package/macos/RCTWebRTC.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -8
- package/metro.config.js +7 -7
- package/metro.config.macos.js +14 -14
- package/package.json +66 -66
- package/react-native.config.js +11 -11
- package/src/.eslintrc.cjs +67 -67
- package/src/Constraints.ts +20 -20
- package/src/EventEmitter.ts +65 -65
- package/src/Logger.ts +49 -49
- package/src/MediaDevices.ts +53 -53
- package/src/MediaStream.ts +161 -161
- package/src/MediaStreamError.ts +12 -12
- package/src/MediaStreamErrorEvent.ts +11 -11
- package/src/MediaStreamTrack.ts +282 -282
- package/src/MediaStreamTrackEvent.ts +25 -25
- package/src/MessageEvent.ts +26 -26
- package/src/Permissions.ts +133 -133
- package/src/RTCAudioSession.ts +25 -25
- package/src/RTCDataChannel.ts +190 -190
- package/src/RTCDataChannelEvent.ts +28 -28
- package/src/RTCDataPacketCryptor.ts +90 -90
- package/src/RTCDataPacketCryptorFactory.ts +24 -24
- package/src/RTCErrorEvent.ts +20 -20
- package/src/RTCFrameCryptor.ts +162 -162
- package/src/RTCFrameCryptorFactory.ts +101 -101
- package/src/RTCIceCandidate.ts +29 -29
- package/src/RTCIceCandidateEvent.ts +26 -26
- package/src/RTCKeyProvider.ts +117 -117
- package/src/RTCPIPView.tsx +46 -46
- package/src/RTCPIPView.web.tsx +18 -18
- package/src/RTCPeerConnection.ts +832 -832
- package/src/RTCRtcpParameters.ts +23 -23
- package/src/RTCRtpCapabilities.ts +16 -16
- package/src/RTCRtpCodecCapability.ts +12 -12
- package/src/RTCRtpCodecParameters.ts +44 -44
- package/src/RTCRtpEncodingParameters.ts +90 -90
- package/src/RTCRtpHeaderExtension.ts +27 -27
- package/src/RTCRtpParameters.ts +37 -37
- package/src/RTCRtpReceiveParameters.ts +7 -7
- package/src/RTCRtpReceiver.ts +60 -60
- package/src/RTCRtpSendParameters.ts +63 -63
- package/src/RTCRtpSender.ts +78 -78
- package/src/RTCRtpTransceiver.ts +107 -107
- package/src/RTCSessionDescription.ts +30 -30
- package/src/RTCTrackEvent.ts +42 -42
- package/src/RTCUtil.ts +211 -211
- package/src/RTCView.ts +122 -122
- package/src/RTCView.web.tsx +80 -80
- package/src/ScreenCapturePickerView.ts +4 -4
- package/src/ScreenCapturePickerView.web.tsx +3 -3
- package/src/getDisplayMedia.ts +30 -30
- package/src/getUserMedia.ts +111 -111
- package/src/index.ts +107 -107
- package/src/index.web.ts +191 -191
- package/src/webStream.ts +31 -31
- package/tools/format.sh +6 -6
- package/tools/release.sh +45 -45
- package/tsconfig.json +17 -17
- package/.claude/settings.local.json +0 -9
|
@@ -1,583 +1,583 @@
|
|
|
1
|
-
package com.oney.WebRTCModule;
|
|
2
|
-
|
|
3
|
-
import android.annotation.SuppressLint;
|
|
4
|
-
import android.content.Context;
|
|
5
|
-
import android.graphics.Color;
|
|
6
|
-
import android.graphics.Point;
|
|
7
|
-
import android.util.Log;
|
|
8
|
-
import android.view.View;
|
|
9
|
-
import android.view.ViewGroup;
|
|
10
|
-
|
|
11
|
-
import androidx.core.view.ViewCompat;
|
|
12
|
-
|
|
13
|
-
import com.facebook.react.bridge.Arguments;
|
|
14
|
-
import com.facebook.react.bridge.Callback;
|
|
15
|
-
import com.facebook.react.bridge.ReactContext;
|
|
16
|
-
import com.facebook.react.bridge.ReadableMap;
|
|
17
|
-
import com.facebook.react.bridge.WritableMap;
|
|
18
|
-
import com.facebook.react.uimanager.events.RCTEventEmitter;
|
|
19
|
-
|
|
20
|
-
import org.webrtc.EglBase;
|
|
21
|
-
import org.webrtc.Logging;
|
|
22
|
-
import org.webrtc.MediaStream;
|
|
23
|
-
import org.webrtc.RendererCommon;
|
|
24
|
-
import org.webrtc.RendererCommon.RendererEvents;
|
|
25
|
-
import org.webrtc.RendererCommon.ScalingType;
|
|
26
|
-
import org.webrtc.SurfaceViewRenderer;
|
|
27
|
-
import org.webrtc.VideoTrack;
|
|
28
|
-
|
|
29
|
-
import java.lang.reflect.InvocationTargetException;
|
|
30
|
-
import java.lang.reflect.Method;
|
|
31
|
-
import java.util.List;
|
|
32
|
-
import java.util.Objects;
|
|
33
|
-
|
|
34
|
-
public class WebRTCView extends ViewGroup {
|
|
35
|
-
/**
|
|
36
|
-
* The scaling type to be utilized by default.
|
|
37
|
-
*
|
|
38
|
-
* The default value is in accord with
|
|
39
|
-
* https://www.w3.org/TR/html5/embedded-content-0.html#the-video-element:
|
|
40
|
-
*
|
|
41
|
-
* In the absence of style rules to the contrary, video content should be
|
|
42
|
-
* rendered inside the element's playback area such that the video content
|
|
43
|
-
* is shown centered in the playback area at the largest possible size that
|
|
44
|
-
* fits completely within it, with the video content's aspect ratio being
|
|
45
|
-
* preserved. Thus, if the aspect ratio of the playback area does not match
|
|
46
|
-
* the aspect ratio of the video, the video will be shown letterboxed or
|
|
47
|
-
* pillarboxed. Areas of the element's playback area that do not contain the
|
|
48
|
-
* video represent nothing.
|
|
49
|
-
*/
|
|
50
|
-
private static final ScalingType DEFAULT_SCALING_TYPE = ScalingType.SCALE_ASPECT_FIT;
|
|
51
|
-
|
|
52
|
-
private static final String TAG = WebRTCModule.TAG;
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* The number of instances for {@link SurfaceViewRenderer}, used for logging.
|
|
56
|
-
* When the renderer is initialized, it creates a new {@link javax.microedition.khronos.egl.EGLContext}
|
|
57
|
-
* which can throw an exception, probably due to memory limitations. We log the number of instances that can
|
|
58
|
-
* be created before the exception is thrown.
|
|
59
|
-
*/
|
|
60
|
-
private static int surfaceViewRendererInstances;
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* The height of the last video frame rendered by
|
|
64
|
-
* {@link #surfaceViewRenderer}.
|
|
65
|
-
*/
|
|
66
|
-
private int frameHeight;
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* The rotation (degree) of the last video frame rendered by
|
|
70
|
-
* {@link #surfaceViewRenderer}.
|
|
71
|
-
*/
|
|
72
|
-
private int frameRotation;
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* The width of the last video frame rendered by
|
|
76
|
-
* {@link #surfaceViewRenderer}.
|
|
77
|
-
*/
|
|
78
|
-
private int frameWidth;
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* The {@code Object} which synchronizes the access to the layout-related
|
|
82
|
-
* state of this instance such as {@link #frameHeight},
|
|
83
|
-
* {@link #frameRotation}, {@link #frameWidth}, and {@link #scalingType}.
|
|
84
|
-
*/
|
|
85
|
-
private final Object layoutSyncRoot = new Object();
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* The indicator which determines whether this {@code WebRTCView} is to
|
|
89
|
-
* mirror the video represented by {@link #videoTrack} during its rendering.
|
|
90
|
-
*/
|
|
91
|
-
private boolean mirror;
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Indicates if the {@link SurfaceViewRenderer} is attached to the video
|
|
95
|
-
* track.
|
|
96
|
-
*/
|
|
97
|
-
private boolean rendererAttached;
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* The {@code RendererEvents} which listens to rendering events reported by
|
|
101
|
-
* {@link #surfaceViewRenderer}.
|
|
102
|
-
*/
|
|
103
|
-
private final RendererEvents rendererEvents = new RendererEvents() {
|
|
104
|
-
@Override
|
|
105
|
-
public void onFirstFrameRendered() {
|
|
106
|
-
WebRTCView.this.onFirstFrameRendered();
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
@Override
|
|
110
|
-
public void onFrameResolutionChanged(int videoWidth, int videoHeight, int rotation) {
|
|
111
|
-
WebRTCView.this.onFrameResolutionChanged(videoWidth, videoHeight, rotation);
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* The {@code Runnable} representation of
|
|
117
|
-
* {@link #requestSurfaceViewRendererLayout()}. Explicitly defined in order
|
|
118
|
-
* to allow the use of the latter with {@link #post(Runnable)} without
|
|
119
|
-
* initializing new instances on every (method) call.
|
|
120
|
-
*/
|
|
121
|
-
private final Runnable requestSurfaceViewRendererLayoutRunnable = new Runnable() {
|
|
122
|
-
@Override
|
|
123
|
-
public void run() {
|
|
124
|
-
requestSurfaceViewRendererLayout();
|
|
125
|
-
}
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* The scaling type this {@code WebRTCView} is to apply to the video
|
|
130
|
-
* represented by {@link #videoTrack} during its rendering. An expression of
|
|
131
|
-
* the CSS property {@code object-fit} in the terms of WebRTC.
|
|
132
|
-
*/
|
|
133
|
-
private ScalingType scalingType;
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* The URL, if any, of the {@link MediaStream} (to be) rendered by this
|
|
137
|
-
* {@code WebRTCView}. The value of {@link #videoTrack} is derived from it.
|
|
138
|
-
*/
|
|
139
|
-
private String streamURL;
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* The {@link View} and {@link VideoSink} implementation which
|
|
143
|
-
* actually renders {@link #videoTrack} on behalf of this instance.
|
|
144
|
-
*/
|
|
145
|
-
private final SurfaceViewRenderer surfaceViewRenderer;
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* The {@code VideoTrack}, if any, rendered by this {@code WebRTCView}.
|
|
149
|
-
*/
|
|
150
|
-
private VideoTrack videoTrack;
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* The callback to be called when video dimensions change.
|
|
154
|
-
*/
|
|
155
|
-
private boolean onDimensionsChangeEnabled = false;
|
|
156
|
-
|
|
157
|
-
public WebRTCView(Context context) {
|
|
158
|
-
super(context);
|
|
159
|
-
|
|
160
|
-
surfaceViewRenderer = new SurfaceViewRenderer(context);
|
|
161
|
-
addView(surfaceViewRenderer);
|
|
162
|
-
|
|
163
|
-
setMirror(false);
|
|
164
|
-
setScalingType(DEFAULT_SCALING_TYPE);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* "Cleans" the {@code SurfaceViewRenderer} by setting the view part to
|
|
169
|
-
* opaque black and the surface part to transparent.
|
|
170
|
-
*/
|
|
171
|
-
private void cleanSurfaceViewRenderer() {
|
|
172
|
-
surfaceViewRenderer.setBackgroundColor(Color.BLACK);
|
|
173
|
-
surfaceViewRenderer.clearImage();
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
private VideoTrack getVideoTrackForStreamURL(String streamURL) {
|
|
177
|
-
VideoTrack videoTrack = null;
|
|
178
|
-
|
|
179
|
-
if (streamURL != null) {
|
|
180
|
-
ReactContext reactContext = (ReactContext) getContext();
|
|
181
|
-
WebRTCModule module = reactContext.getNativeModule(WebRTCModule.class);
|
|
182
|
-
MediaStream stream = module.getStreamForReactTag(streamURL);
|
|
183
|
-
|
|
184
|
-
if (stream != null) {
|
|
185
|
-
List<VideoTrack> videoTracks = stream.videoTracks;
|
|
186
|
-
|
|
187
|
-
if (!videoTracks.isEmpty()) {
|
|
188
|
-
videoTrack = videoTracks.get(0);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
if (videoTrack == null) {
|
|
193
|
-
Log.w(TAG, "No video stream for react tag: " + streamURL);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
return videoTrack;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
@Override
|
|
201
|
-
protected void onAttachedToWindow() {
|
|
202
|
-
try {
|
|
203
|
-
// Generally, OpenGL is only necessary while this View is attached
|
|
204
|
-
// to a window so there is no point in having the whole rendering
|
|
205
|
-
// infrastructure hooked up while this View is not attached to a
|
|
206
|
-
// window. Additionally, a memory leak was solved in a similar way
|
|
207
|
-
// on iOS.
|
|
208
|
-
tryAddRendererToVideoTrack();
|
|
209
|
-
} finally {
|
|
210
|
-
super.onAttachedToWindow();
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
@Override
|
|
215
|
-
protected void onDetachedFromWindow() {
|
|
216
|
-
try {
|
|
217
|
-
// Generally, OpenGL is only necessary while this View is attached
|
|
218
|
-
// to a window so there is no point in having the whole rendering
|
|
219
|
-
// infrastructure hooked up while this View is not attached to a
|
|
220
|
-
// window. Additionally, a memory leak was solved in a similar way
|
|
221
|
-
// on iOS.
|
|
222
|
-
removeRendererFromVideoTrack();
|
|
223
|
-
} finally {
|
|
224
|
-
super.onDetachedFromWindow();
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Callback fired by {@link #surfaceViewRenderer} when the first frame is
|
|
230
|
-
* rendered. Here we will set the background of the view part of the
|
|
231
|
-
* SurfaceView to transparent, so the surface (where video is actually
|
|
232
|
-
* rendered) shines through.
|
|
233
|
-
*/
|
|
234
|
-
private void onFirstFrameRendered() {
|
|
235
|
-
post(() -> {
|
|
236
|
-
Log.d(TAG, "First frame rendered.");
|
|
237
|
-
surfaceViewRenderer.setBackgroundColor(Color.TRANSPARENT);
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* Callback fired by {@link #surfaceViewRenderer} when the resolution or
|
|
243
|
-
* rotation of the frame it renders has changed.
|
|
244
|
-
*
|
|
245
|
-
* @param videoWidth The new width of the rendered video frame.
|
|
246
|
-
* @param videoHeight The new height of the rendered video frame.
|
|
247
|
-
* @param rotation The new rotation of the rendered video frame.
|
|
248
|
-
*/
|
|
249
|
-
private void onFrameResolutionChanged(int videoWidth, int videoHeight, int rotation) {
|
|
250
|
-
boolean changed = false;
|
|
251
|
-
|
|
252
|
-
synchronized (layoutSyncRoot) {
|
|
253
|
-
if (this.frameHeight != videoHeight) {
|
|
254
|
-
this.frameHeight = videoHeight;
|
|
255
|
-
changed = true;
|
|
256
|
-
}
|
|
257
|
-
if (this.frameRotation != rotation) {
|
|
258
|
-
this.frameRotation = rotation;
|
|
259
|
-
changed = true;
|
|
260
|
-
}
|
|
261
|
-
if (this.frameWidth != videoWidth) {
|
|
262
|
-
this.frameWidth = videoWidth;
|
|
263
|
-
changed = true;
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
if (changed) {
|
|
267
|
-
// The onFrameResolutionChanged method call executes on the
|
|
268
|
-
// surfaceViewRenderer's render Thread.
|
|
269
|
-
post(requestSurfaceViewRendererLayoutRunnable);
|
|
270
|
-
|
|
271
|
-
// Call the onDimensionsChange callback if it's enabled
|
|
272
|
-
if (onDimensionsChangeEnabled) {
|
|
273
|
-
post(() -> {
|
|
274
|
-
try {
|
|
275
|
-
ReactContext reactContext = (ReactContext) getContext();
|
|
276
|
-
WritableMap params = Arguments.createMap();
|
|
277
|
-
params.putInt("width", videoWidth);
|
|
278
|
-
params.putInt("height", videoHeight);
|
|
279
|
-
|
|
280
|
-
// Send the event through React Native's event system
|
|
281
|
-
reactContext.getJSModule(RCTEventEmitter.class)
|
|
282
|
-
.receiveEvent(getId(), "onDimensionsChange", params);
|
|
283
|
-
} catch (Exception e) {
|
|
284
|
-
Log.e(TAG, "Error calling onDimensionsChange callback", e);
|
|
285
|
-
}
|
|
286
|
-
});
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
@Override
|
|
292
|
-
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
|
293
|
-
int height = b - t;
|
|
294
|
-
int width = r - l;
|
|
295
|
-
|
|
296
|
-
if (height == 0 || width == 0) {
|
|
297
|
-
l = t = r = b = 0;
|
|
298
|
-
} else {
|
|
299
|
-
int frameHeight;
|
|
300
|
-
int frameRotation;
|
|
301
|
-
int frameWidth;
|
|
302
|
-
ScalingType scalingType;
|
|
303
|
-
|
|
304
|
-
synchronized (layoutSyncRoot) {
|
|
305
|
-
frameHeight = this.frameHeight;
|
|
306
|
-
frameRotation = this.frameRotation;
|
|
307
|
-
frameWidth = this.frameWidth;
|
|
308
|
-
scalingType = this.scalingType;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
switch (scalingType) {
|
|
312
|
-
case SCALE_ASPECT_FILL:
|
|
313
|
-
// Fill this ViewGroup with surfaceViewRenderer and the latter
|
|
314
|
-
// will take care of filling itself with the video similarly to
|
|
315
|
-
// the cover value the CSS property object-fit.
|
|
316
|
-
r = width;
|
|
317
|
-
l = 0;
|
|
318
|
-
b = height;
|
|
319
|
-
t = 0;
|
|
320
|
-
break;
|
|
321
|
-
case SCALE_ASPECT_FIT:
|
|
322
|
-
default:
|
|
323
|
-
// Lay surfaceViewRenderer out inside this ViewGroup in accord
|
|
324
|
-
// with the contain value of the CSS property object-fit.
|
|
325
|
-
// SurfaceViewRenderer will fill itself with the video similarly
|
|
326
|
-
// to the cover or contain value of the CSS property object-fit
|
|
327
|
-
// (which will not matter, eventually).
|
|
328
|
-
if (frameHeight == 0 || frameWidth == 0) {
|
|
329
|
-
l = t = r = b = 0;
|
|
330
|
-
} else {
|
|
331
|
-
float frameAspectRatio = (frameRotation % 180 == 0) ? frameWidth / (float) frameHeight
|
|
332
|
-
: frameHeight / (float) frameWidth;
|
|
333
|
-
Point frameDisplaySize =
|
|
334
|
-
RendererCommon.getDisplaySize(scalingType, frameAspectRatio, width, height);
|
|
335
|
-
|
|
336
|
-
l = (width - frameDisplaySize.x) / 2;
|
|
337
|
-
t = (height - frameDisplaySize.y) / 2;
|
|
338
|
-
r = l + frameDisplaySize.x;
|
|
339
|
-
b = t + frameDisplaySize.y;
|
|
340
|
-
}
|
|
341
|
-
break;
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
surfaceViewRenderer.layout(l, t, r, b);
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
/**
|
|
348
|
-
* Stops rendering {@link #videoTrack} and releases the associated acquired
|
|
349
|
-
* resources (if rendering is in progress).
|
|
350
|
-
*/
|
|
351
|
-
private void removeRendererFromVideoTrack() {
|
|
352
|
-
if (rendererAttached) {
|
|
353
|
-
if (videoTrack != null) {
|
|
354
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
355
|
-
try {
|
|
356
|
-
videoTrack.removeSink(surfaceViewRenderer);
|
|
357
|
-
} catch (Throwable tr) {
|
|
358
|
-
// XXX If WebRTCModule#mediaStreamTrackRelease has already been
|
|
359
|
-
// invoked on videoTrack, then it is no longer safe to call removeSink
|
|
360
|
-
// on the instance, it will throw IllegalStateException.
|
|
361
|
-
}
|
|
362
|
-
});
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
surfaceViewRenderer.release();
|
|
366
|
-
surfaceViewRendererInstances--;
|
|
367
|
-
rendererAttached = false;
|
|
368
|
-
|
|
369
|
-
// Since this WebRTCView is no longer rendering anything, make sure
|
|
370
|
-
// surfaceViewRenderer displays nothing as well.
|
|
371
|
-
synchronized (layoutSyncRoot) {
|
|
372
|
-
frameHeight = 0;
|
|
373
|
-
frameRotation = 0;
|
|
374
|
-
frameWidth = 0;
|
|
375
|
-
}
|
|
376
|
-
requestSurfaceViewRendererLayout();
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
/**
|
|
381
|
-
* Request that {@link #surfaceViewRenderer} be laid out (as soon as
|
|
382
|
-
* possible) because layout-related state either of this instance or of
|
|
383
|
-
* {@code surfaceViewRenderer} has changed.
|
|
384
|
-
*/
|
|
385
|
-
@SuppressLint("WrongCall")
|
|
386
|
-
private void requestSurfaceViewRendererLayout() {
|
|
387
|
-
// Google/WebRTC just call requestLayout() on surfaceViewRenderer when
|
|
388
|
-
// they change the value of its mirror or surfaceType property.
|
|
389
|
-
surfaceViewRenderer.requestLayout();
|
|
390
|
-
// The above is not enough though when the video frame's dimensions or
|
|
391
|
-
// rotation change. The following will suffice.
|
|
392
|
-
if (!ViewCompat.isInLayout(this)) {
|
|
393
|
-
onLayout(
|
|
394
|
-
/* changed */ false, getLeft(), getTop(), getRight(), getBottom());
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
/**
|
|
399
|
-
* Sets the indicator which determines whether this {@code WebRTCView} is to
|
|
400
|
-
* mirror the video represented by {@link #videoTrack} during its rendering.
|
|
401
|
-
*
|
|
402
|
-
* @param mirror If this {@code WebRTCView} is to mirror the video
|
|
403
|
-
* represented by {@code videoTrack} during its rendering, {@code true};
|
|
404
|
-
* otherwise, {@code false}.
|
|
405
|
-
*/
|
|
406
|
-
public void setMirror(boolean mirror) {
|
|
407
|
-
if (this.mirror != mirror) {
|
|
408
|
-
this.mirror = mirror;
|
|
409
|
-
surfaceViewRenderer.setMirror(mirror);
|
|
410
|
-
// SurfaceViewRenderer takes the value of its mirror property into
|
|
411
|
-
// account upon its layout.
|
|
412
|
-
requestSurfaceViewRendererLayout();
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
/**
|
|
417
|
-
* In the fashion of
|
|
418
|
-
* https://www.w3.org/TR/html5/embedded-content-0.html#dom-video-videowidth
|
|
419
|
-
* and https://www.w3.org/TR/html5/rendering.html#video-object-fit,
|
|
420
|
-
* resembles the CSS style {@code object-fit}.
|
|
421
|
-
*
|
|
422
|
-
* @param objectFit For details, refer to the documentation of the
|
|
423
|
-
* {@code objectFit} property of the JavaScript counterpart of
|
|
424
|
-
* {@code WebRTCView} i.e. {@code RTCView}.
|
|
425
|
-
*/
|
|
426
|
-
public void setObjectFit(String objectFit) {
|
|
427
|
-
ScalingType scalingType =
|
|
428
|
-
"cover".equals(objectFit) ? ScalingType.SCALE_ASPECT_FILL : ScalingType.SCALE_ASPECT_FIT;
|
|
429
|
-
|
|
430
|
-
setScalingType(scalingType);
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
private void setScalingType(ScalingType scalingType) {
|
|
434
|
-
synchronized (layoutSyncRoot) {
|
|
435
|
-
if (this.scalingType == scalingType) {
|
|
436
|
-
return;
|
|
437
|
-
}
|
|
438
|
-
this.scalingType = scalingType;
|
|
439
|
-
surfaceViewRenderer.setScalingType(scalingType);
|
|
440
|
-
}
|
|
441
|
-
// Both this instance ant its SurfaceViewRenderer take the value of
|
|
442
|
-
// their scalingType properties into account upon their layouts.
|
|
443
|
-
requestSurfaceViewRendererLayout();
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
/**
|
|
447
|
-
* Sets the {@code MediaStream} to be rendered by this {@code WebRTCView}.
|
|
448
|
-
* The implementation renders the first {@link VideoTrack}, if any, of the
|
|
449
|
-
* specified {@code mediaStream}.
|
|
450
|
-
*
|
|
451
|
-
* @param streamURL The URL of the {@code MediaStream} to be rendered by
|
|
452
|
-
* this {@code WebRTCView} or {@code null}.
|
|
453
|
-
*/
|
|
454
|
-
void setStreamURL(String streamURL) {
|
|
455
|
-
// Is the value of this.streamURL really changing?
|
|
456
|
-
if (!Objects.equals(streamURL, this.streamURL)) {
|
|
457
|
-
// XXX The value of this.streamURL is really changing. Before
|
|
458
|
-
// realizing/applying the change, let go of the old videoTrack. Of
|
|
459
|
-
// course, that is only necessary if the value of videoTrack will
|
|
460
|
-
// really change. Please note though that letting go of the old
|
|
461
|
-
// videoTrack before assigning to this.streamURL is vital;
|
|
462
|
-
// otherwise, removeRendererFromVideoTrack will fail to remove the
|
|
463
|
-
// old videoTrack from the associated videoRenderer, two
|
|
464
|
-
// VideoTracks (the old and the new) may start rendering and, most
|
|
465
|
-
// importantly the videoRender may eventually crash when the old
|
|
466
|
-
// videoTrack is disposed.
|
|
467
|
-
VideoTrack videoTrack = getVideoTrackForStreamURL(streamURL);
|
|
468
|
-
|
|
469
|
-
if (this.videoTrack != videoTrack) {
|
|
470
|
-
setVideoTrack(null);
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
this.streamURL = streamURL;
|
|
474
|
-
|
|
475
|
-
// After realizing/applying the change in the value of
|
|
476
|
-
// this.streamURL, reflect it on the value of videoTrack.
|
|
477
|
-
setVideoTrack(videoTrack);
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
/**
|
|
482
|
-
* Sets the {@code VideoTrack} to be rendered by this {@code WebRTCView}.
|
|
483
|
-
*
|
|
484
|
-
* @param videoTrack The {@code VideoTrack} to be rendered by this
|
|
485
|
-
* {@code WebRTCView} or {@code null}.
|
|
486
|
-
*/
|
|
487
|
-
private void setVideoTrack(VideoTrack videoTrack) {
|
|
488
|
-
VideoTrack oldVideoTrack = this.videoTrack;
|
|
489
|
-
|
|
490
|
-
if (oldVideoTrack != videoTrack) {
|
|
491
|
-
if (oldVideoTrack != null) {
|
|
492
|
-
if (videoTrack == null) {
|
|
493
|
-
// If we are not going to render any stream, clean the
|
|
494
|
-
// surface.
|
|
495
|
-
cleanSurfaceViewRenderer();
|
|
496
|
-
}
|
|
497
|
-
removeRendererFromVideoTrack();
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
this.videoTrack = videoTrack;
|
|
501
|
-
|
|
502
|
-
if (videoTrack != null) {
|
|
503
|
-
tryAddRendererToVideoTrack();
|
|
504
|
-
if (oldVideoTrack == null) {
|
|
505
|
-
// If there was no old track, clean the surface so we start
|
|
506
|
-
// with black.
|
|
507
|
-
cleanSurfaceViewRenderer();
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
/**
|
|
514
|
-
* Sets the z-order of this {@link WebRTCView} in the stacking space of all
|
|
515
|
-
* {@code WebRTCView}s. For more details, refer to the documentation of the
|
|
516
|
-
* {@code zOrder} property of the JavaScript counterpart of
|
|
517
|
-
* {@code WebRTCView} i.e. {@code RTCView}.
|
|
518
|
-
*
|
|
519
|
-
* @param zOrder The z-order to set on this {@code WebRTCView}.
|
|
520
|
-
*/
|
|
521
|
-
public void setZOrder(int zOrder) {
|
|
522
|
-
switch (zOrder) {
|
|
523
|
-
case 0:
|
|
524
|
-
surfaceViewRenderer.setZOrderMediaOverlay(false);
|
|
525
|
-
break;
|
|
526
|
-
case 1:
|
|
527
|
-
surfaceViewRenderer.setZOrderMediaOverlay(true);
|
|
528
|
-
break;
|
|
529
|
-
case 2:
|
|
530
|
-
surfaceViewRenderer.setZOrderOnTop(true);
|
|
531
|
-
break;
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
/**
|
|
536
|
-
* Starts rendering {@link #videoTrack} if rendering is not in progress and
|
|
537
|
-
* all preconditions for the start of rendering are met.
|
|
538
|
-
*/
|
|
539
|
-
private void tryAddRendererToVideoTrack() {
|
|
540
|
-
if (!rendererAttached && videoTrack != null && ViewCompat.isAttachedToWindow(this)) {
|
|
541
|
-
EglBase.Context sharedContext = EglUtils.getRootEglBaseContext();
|
|
542
|
-
|
|
543
|
-
if (sharedContext == null) {
|
|
544
|
-
// If SurfaceViewRenderer#init() is invoked, it will throw a
|
|
545
|
-
// RuntimeException which will very likely kill the application.
|
|
546
|
-
Log.e(TAG, "Failed to render a VideoTrack!");
|
|
547
|
-
return;
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
try {
|
|
551
|
-
surfaceViewRenderer.init(sharedContext, rendererEvents);
|
|
552
|
-
surfaceViewRendererInstances++;
|
|
553
|
-
} catch (Exception e) {
|
|
554
|
-
Logging.e(
|
|
555
|
-
TAG, "Failed to initialize surfaceViewRenderer on instance " + surfaceViewRendererInstances, e);
|
|
556
|
-
return;
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
560
|
-
try {
|
|
561
|
-
videoTrack.addSink(surfaceViewRenderer);
|
|
562
|
-
} catch (Throwable tr) {
|
|
563
|
-
// XXX If WebRTCModule#mediaStreamTrackRelease has already been
|
|
564
|
-
// invoked on videoTrack, then it is no longer safe to call addSink
|
|
565
|
-
// on the instance, it will throw IllegalStateException.
|
|
566
|
-
|
|
567
|
-
Log.e(TAG, "Failed to add renderer", tr);
|
|
568
|
-
}
|
|
569
|
-
});
|
|
570
|
-
|
|
571
|
-
rendererAttached = true;
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
/**
|
|
576
|
-
* Sets whether the onDimensionsChange callback should be called.
|
|
577
|
-
*
|
|
578
|
-
* @param enabled Whether the callback should be enabled.
|
|
579
|
-
*/
|
|
580
|
-
public void setOnDimensionsChange(boolean enabled) {
|
|
581
|
-
this.onDimensionsChangeEnabled = enabled;
|
|
582
|
-
}
|
|
583
|
-
}
|
|
1
|
+
package com.oney.WebRTCModule;
|
|
2
|
+
|
|
3
|
+
import android.annotation.SuppressLint;
|
|
4
|
+
import android.content.Context;
|
|
5
|
+
import android.graphics.Color;
|
|
6
|
+
import android.graphics.Point;
|
|
7
|
+
import android.util.Log;
|
|
8
|
+
import android.view.View;
|
|
9
|
+
import android.view.ViewGroup;
|
|
10
|
+
|
|
11
|
+
import androidx.core.view.ViewCompat;
|
|
12
|
+
|
|
13
|
+
import com.facebook.react.bridge.Arguments;
|
|
14
|
+
import com.facebook.react.bridge.Callback;
|
|
15
|
+
import com.facebook.react.bridge.ReactContext;
|
|
16
|
+
import com.facebook.react.bridge.ReadableMap;
|
|
17
|
+
import com.facebook.react.bridge.WritableMap;
|
|
18
|
+
import com.facebook.react.uimanager.events.RCTEventEmitter;
|
|
19
|
+
|
|
20
|
+
import org.webrtc.EglBase;
|
|
21
|
+
import org.webrtc.Logging;
|
|
22
|
+
import org.webrtc.MediaStream;
|
|
23
|
+
import org.webrtc.RendererCommon;
|
|
24
|
+
import org.webrtc.RendererCommon.RendererEvents;
|
|
25
|
+
import org.webrtc.RendererCommon.ScalingType;
|
|
26
|
+
import org.webrtc.SurfaceViewRenderer;
|
|
27
|
+
import org.webrtc.VideoTrack;
|
|
28
|
+
|
|
29
|
+
import java.lang.reflect.InvocationTargetException;
|
|
30
|
+
import java.lang.reflect.Method;
|
|
31
|
+
import java.util.List;
|
|
32
|
+
import java.util.Objects;
|
|
33
|
+
|
|
34
|
+
public class WebRTCView extends ViewGroup {
|
|
35
|
+
/**
|
|
36
|
+
* The scaling type to be utilized by default.
|
|
37
|
+
*
|
|
38
|
+
* The default value is in accord with
|
|
39
|
+
* https://www.w3.org/TR/html5/embedded-content-0.html#the-video-element:
|
|
40
|
+
*
|
|
41
|
+
* In the absence of style rules to the contrary, video content should be
|
|
42
|
+
* rendered inside the element's playback area such that the video content
|
|
43
|
+
* is shown centered in the playback area at the largest possible size that
|
|
44
|
+
* fits completely within it, with the video content's aspect ratio being
|
|
45
|
+
* preserved. Thus, if the aspect ratio of the playback area does not match
|
|
46
|
+
* the aspect ratio of the video, the video will be shown letterboxed or
|
|
47
|
+
* pillarboxed. Areas of the element's playback area that do not contain the
|
|
48
|
+
* video represent nothing.
|
|
49
|
+
*/
|
|
50
|
+
private static final ScalingType DEFAULT_SCALING_TYPE = ScalingType.SCALE_ASPECT_FIT;
|
|
51
|
+
|
|
52
|
+
private static final String TAG = WebRTCModule.TAG;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The number of instances for {@link SurfaceViewRenderer}, used for logging.
|
|
56
|
+
* When the renderer is initialized, it creates a new {@link javax.microedition.khronos.egl.EGLContext}
|
|
57
|
+
* which can throw an exception, probably due to memory limitations. We log the number of instances that can
|
|
58
|
+
* be created before the exception is thrown.
|
|
59
|
+
*/
|
|
60
|
+
private static int surfaceViewRendererInstances;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* The height of the last video frame rendered by
|
|
64
|
+
* {@link #surfaceViewRenderer}.
|
|
65
|
+
*/
|
|
66
|
+
private int frameHeight;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* The rotation (degree) of the last video frame rendered by
|
|
70
|
+
* {@link #surfaceViewRenderer}.
|
|
71
|
+
*/
|
|
72
|
+
private int frameRotation;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* The width of the last video frame rendered by
|
|
76
|
+
* {@link #surfaceViewRenderer}.
|
|
77
|
+
*/
|
|
78
|
+
private int frameWidth;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* The {@code Object} which synchronizes the access to the layout-related
|
|
82
|
+
* state of this instance such as {@link #frameHeight},
|
|
83
|
+
* {@link #frameRotation}, {@link #frameWidth}, and {@link #scalingType}.
|
|
84
|
+
*/
|
|
85
|
+
private final Object layoutSyncRoot = new Object();
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* The indicator which determines whether this {@code WebRTCView} is to
|
|
89
|
+
* mirror the video represented by {@link #videoTrack} during its rendering.
|
|
90
|
+
*/
|
|
91
|
+
private boolean mirror;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Indicates if the {@link SurfaceViewRenderer} is attached to the video
|
|
95
|
+
* track.
|
|
96
|
+
*/
|
|
97
|
+
private boolean rendererAttached;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* The {@code RendererEvents} which listens to rendering events reported by
|
|
101
|
+
* {@link #surfaceViewRenderer}.
|
|
102
|
+
*/
|
|
103
|
+
private final RendererEvents rendererEvents = new RendererEvents() {
|
|
104
|
+
@Override
|
|
105
|
+
public void onFirstFrameRendered() {
|
|
106
|
+
WebRTCView.this.onFirstFrameRendered();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
@Override
|
|
110
|
+
public void onFrameResolutionChanged(int videoWidth, int videoHeight, int rotation) {
|
|
111
|
+
WebRTCView.this.onFrameResolutionChanged(videoWidth, videoHeight, rotation);
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* The {@code Runnable} representation of
|
|
117
|
+
* {@link #requestSurfaceViewRendererLayout()}. Explicitly defined in order
|
|
118
|
+
* to allow the use of the latter with {@link #post(Runnable)} without
|
|
119
|
+
* initializing new instances on every (method) call.
|
|
120
|
+
*/
|
|
121
|
+
private final Runnable requestSurfaceViewRendererLayoutRunnable = new Runnable() {
|
|
122
|
+
@Override
|
|
123
|
+
public void run() {
|
|
124
|
+
requestSurfaceViewRendererLayout();
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* The scaling type this {@code WebRTCView} is to apply to the video
|
|
130
|
+
* represented by {@link #videoTrack} during its rendering. An expression of
|
|
131
|
+
* the CSS property {@code object-fit} in the terms of WebRTC.
|
|
132
|
+
*/
|
|
133
|
+
private ScalingType scalingType;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* The URL, if any, of the {@link MediaStream} (to be) rendered by this
|
|
137
|
+
* {@code WebRTCView}. The value of {@link #videoTrack} is derived from it.
|
|
138
|
+
*/
|
|
139
|
+
private String streamURL;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* The {@link View} and {@link VideoSink} implementation which
|
|
143
|
+
* actually renders {@link #videoTrack} on behalf of this instance.
|
|
144
|
+
*/
|
|
145
|
+
private final SurfaceViewRenderer surfaceViewRenderer;
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* The {@code VideoTrack}, if any, rendered by this {@code WebRTCView}.
|
|
149
|
+
*/
|
|
150
|
+
private VideoTrack videoTrack;
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* The callback to be called when video dimensions change.
|
|
154
|
+
*/
|
|
155
|
+
private boolean onDimensionsChangeEnabled = false;
|
|
156
|
+
|
|
157
|
+
public WebRTCView(Context context) {
|
|
158
|
+
super(context);
|
|
159
|
+
|
|
160
|
+
surfaceViewRenderer = new SurfaceViewRenderer(context);
|
|
161
|
+
addView(surfaceViewRenderer);
|
|
162
|
+
|
|
163
|
+
setMirror(false);
|
|
164
|
+
setScalingType(DEFAULT_SCALING_TYPE);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* "Cleans" the {@code SurfaceViewRenderer} by setting the view part to
|
|
169
|
+
* opaque black and the surface part to transparent.
|
|
170
|
+
*/
|
|
171
|
+
private void cleanSurfaceViewRenderer() {
|
|
172
|
+
surfaceViewRenderer.setBackgroundColor(Color.BLACK);
|
|
173
|
+
surfaceViewRenderer.clearImage();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
private VideoTrack getVideoTrackForStreamURL(String streamURL) {
|
|
177
|
+
VideoTrack videoTrack = null;
|
|
178
|
+
|
|
179
|
+
if (streamURL != null) {
|
|
180
|
+
ReactContext reactContext = (ReactContext) getContext();
|
|
181
|
+
WebRTCModule module = reactContext.getNativeModule(WebRTCModule.class);
|
|
182
|
+
MediaStream stream = module.getStreamForReactTag(streamURL);
|
|
183
|
+
|
|
184
|
+
if (stream != null) {
|
|
185
|
+
List<VideoTrack> videoTracks = stream.videoTracks;
|
|
186
|
+
|
|
187
|
+
if (!videoTracks.isEmpty()) {
|
|
188
|
+
videoTrack = videoTracks.get(0);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (videoTrack == null) {
|
|
193
|
+
Log.w(TAG, "No video stream for react tag: " + streamURL);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return videoTrack;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
@Override
|
|
201
|
+
protected void onAttachedToWindow() {
|
|
202
|
+
try {
|
|
203
|
+
// Generally, OpenGL is only necessary while this View is attached
|
|
204
|
+
// to a window so there is no point in having the whole rendering
|
|
205
|
+
// infrastructure hooked up while this View is not attached to a
|
|
206
|
+
// window. Additionally, a memory leak was solved in a similar way
|
|
207
|
+
// on iOS.
|
|
208
|
+
tryAddRendererToVideoTrack();
|
|
209
|
+
} finally {
|
|
210
|
+
super.onAttachedToWindow();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
@Override
|
|
215
|
+
protected void onDetachedFromWindow() {
|
|
216
|
+
try {
|
|
217
|
+
// Generally, OpenGL is only necessary while this View is attached
|
|
218
|
+
// to a window so there is no point in having the whole rendering
|
|
219
|
+
// infrastructure hooked up while this View is not attached to a
|
|
220
|
+
// window. Additionally, a memory leak was solved in a similar way
|
|
221
|
+
// on iOS.
|
|
222
|
+
removeRendererFromVideoTrack();
|
|
223
|
+
} finally {
|
|
224
|
+
super.onDetachedFromWindow();
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Callback fired by {@link #surfaceViewRenderer} when the first frame is
|
|
230
|
+
* rendered. Here we will set the background of the view part of the
|
|
231
|
+
* SurfaceView to transparent, so the surface (where video is actually
|
|
232
|
+
* rendered) shines through.
|
|
233
|
+
*/
|
|
234
|
+
private void onFirstFrameRendered() {
|
|
235
|
+
post(() -> {
|
|
236
|
+
Log.d(TAG, "First frame rendered.");
|
|
237
|
+
surfaceViewRenderer.setBackgroundColor(Color.TRANSPARENT);
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Callback fired by {@link #surfaceViewRenderer} when the resolution or
|
|
243
|
+
* rotation of the frame it renders has changed.
|
|
244
|
+
*
|
|
245
|
+
* @param videoWidth The new width of the rendered video frame.
|
|
246
|
+
* @param videoHeight The new height of the rendered video frame.
|
|
247
|
+
* @param rotation The new rotation of the rendered video frame.
|
|
248
|
+
*/
|
|
249
|
+
private void onFrameResolutionChanged(int videoWidth, int videoHeight, int rotation) {
|
|
250
|
+
boolean changed = false;
|
|
251
|
+
|
|
252
|
+
synchronized (layoutSyncRoot) {
|
|
253
|
+
if (this.frameHeight != videoHeight) {
|
|
254
|
+
this.frameHeight = videoHeight;
|
|
255
|
+
changed = true;
|
|
256
|
+
}
|
|
257
|
+
if (this.frameRotation != rotation) {
|
|
258
|
+
this.frameRotation = rotation;
|
|
259
|
+
changed = true;
|
|
260
|
+
}
|
|
261
|
+
if (this.frameWidth != videoWidth) {
|
|
262
|
+
this.frameWidth = videoWidth;
|
|
263
|
+
changed = true;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
if (changed) {
|
|
267
|
+
// The onFrameResolutionChanged method call executes on the
|
|
268
|
+
// surfaceViewRenderer's render Thread.
|
|
269
|
+
post(requestSurfaceViewRendererLayoutRunnable);
|
|
270
|
+
|
|
271
|
+
// Call the onDimensionsChange callback if it's enabled
|
|
272
|
+
if (onDimensionsChangeEnabled) {
|
|
273
|
+
post(() -> {
|
|
274
|
+
try {
|
|
275
|
+
ReactContext reactContext = (ReactContext) getContext();
|
|
276
|
+
WritableMap params = Arguments.createMap();
|
|
277
|
+
params.putInt("width", videoWidth);
|
|
278
|
+
params.putInt("height", videoHeight);
|
|
279
|
+
|
|
280
|
+
// Send the event through React Native's event system
|
|
281
|
+
reactContext.getJSModule(RCTEventEmitter.class)
|
|
282
|
+
.receiveEvent(getId(), "onDimensionsChange", params);
|
|
283
|
+
} catch (Exception e) {
|
|
284
|
+
Log.e(TAG, "Error calling onDimensionsChange callback", e);
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
@Override
|
|
292
|
+
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
|
293
|
+
int height = b - t;
|
|
294
|
+
int width = r - l;
|
|
295
|
+
|
|
296
|
+
if (height == 0 || width == 0) {
|
|
297
|
+
l = t = r = b = 0;
|
|
298
|
+
} else {
|
|
299
|
+
int frameHeight;
|
|
300
|
+
int frameRotation;
|
|
301
|
+
int frameWidth;
|
|
302
|
+
ScalingType scalingType;
|
|
303
|
+
|
|
304
|
+
synchronized (layoutSyncRoot) {
|
|
305
|
+
frameHeight = this.frameHeight;
|
|
306
|
+
frameRotation = this.frameRotation;
|
|
307
|
+
frameWidth = this.frameWidth;
|
|
308
|
+
scalingType = this.scalingType;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
switch (scalingType) {
|
|
312
|
+
case SCALE_ASPECT_FILL:
|
|
313
|
+
// Fill this ViewGroup with surfaceViewRenderer and the latter
|
|
314
|
+
// will take care of filling itself with the video similarly to
|
|
315
|
+
// the cover value the CSS property object-fit.
|
|
316
|
+
r = width;
|
|
317
|
+
l = 0;
|
|
318
|
+
b = height;
|
|
319
|
+
t = 0;
|
|
320
|
+
break;
|
|
321
|
+
case SCALE_ASPECT_FIT:
|
|
322
|
+
default:
|
|
323
|
+
// Lay surfaceViewRenderer out inside this ViewGroup in accord
|
|
324
|
+
// with the contain value of the CSS property object-fit.
|
|
325
|
+
// SurfaceViewRenderer will fill itself with the video similarly
|
|
326
|
+
// to the cover or contain value of the CSS property object-fit
|
|
327
|
+
// (which will not matter, eventually).
|
|
328
|
+
if (frameHeight == 0 || frameWidth == 0) {
|
|
329
|
+
l = t = r = b = 0;
|
|
330
|
+
} else {
|
|
331
|
+
float frameAspectRatio = (frameRotation % 180 == 0) ? frameWidth / (float) frameHeight
|
|
332
|
+
: frameHeight / (float) frameWidth;
|
|
333
|
+
Point frameDisplaySize =
|
|
334
|
+
RendererCommon.getDisplaySize(scalingType, frameAspectRatio, width, height);
|
|
335
|
+
|
|
336
|
+
l = (width - frameDisplaySize.x) / 2;
|
|
337
|
+
t = (height - frameDisplaySize.y) / 2;
|
|
338
|
+
r = l + frameDisplaySize.x;
|
|
339
|
+
b = t + frameDisplaySize.y;
|
|
340
|
+
}
|
|
341
|
+
break;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
surfaceViewRenderer.layout(l, t, r, b);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Stops rendering {@link #videoTrack} and releases the associated acquired
|
|
349
|
+
* resources (if rendering is in progress).
|
|
350
|
+
*/
|
|
351
|
+
private void removeRendererFromVideoTrack() {
|
|
352
|
+
if (rendererAttached) {
|
|
353
|
+
if (videoTrack != null) {
|
|
354
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
355
|
+
try {
|
|
356
|
+
videoTrack.removeSink(surfaceViewRenderer);
|
|
357
|
+
} catch (Throwable tr) {
|
|
358
|
+
// XXX If WebRTCModule#mediaStreamTrackRelease has already been
|
|
359
|
+
// invoked on videoTrack, then it is no longer safe to call removeSink
|
|
360
|
+
// on the instance, it will throw IllegalStateException.
|
|
361
|
+
}
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
surfaceViewRenderer.release();
|
|
366
|
+
surfaceViewRendererInstances--;
|
|
367
|
+
rendererAttached = false;
|
|
368
|
+
|
|
369
|
+
// Since this WebRTCView is no longer rendering anything, make sure
|
|
370
|
+
// surfaceViewRenderer displays nothing as well.
|
|
371
|
+
synchronized (layoutSyncRoot) {
|
|
372
|
+
frameHeight = 0;
|
|
373
|
+
frameRotation = 0;
|
|
374
|
+
frameWidth = 0;
|
|
375
|
+
}
|
|
376
|
+
requestSurfaceViewRendererLayout();
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Request that {@link #surfaceViewRenderer} be laid out (as soon as
|
|
382
|
+
* possible) because layout-related state either of this instance or of
|
|
383
|
+
* {@code surfaceViewRenderer} has changed.
|
|
384
|
+
*/
|
|
385
|
+
@SuppressLint("WrongCall")
|
|
386
|
+
private void requestSurfaceViewRendererLayout() {
|
|
387
|
+
// Google/WebRTC just call requestLayout() on surfaceViewRenderer when
|
|
388
|
+
// they change the value of its mirror or surfaceType property.
|
|
389
|
+
surfaceViewRenderer.requestLayout();
|
|
390
|
+
// The above is not enough though when the video frame's dimensions or
|
|
391
|
+
// rotation change. The following will suffice.
|
|
392
|
+
if (!ViewCompat.isInLayout(this)) {
|
|
393
|
+
onLayout(
|
|
394
|
+
/* changed */ false, getLeft(), getTop(), getRight(), getBottom());
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Sets the indicator which determines whether this {@code WebRTCView} is to
|
|
400
|
+
* mirror the video represented by {@link #videoTrack} during its rendering.
|
|
401
|
+
*
|
|
402
|
+
* @param mirror If this {@code WebRTCView} is to mirror the video
|
|
403
|
+
* represented by {@code videoTrack} during its rendering, {@code true};
|
|
404
|
+
* otherwise, {@code false}.
|
|
405
|
+
*/
|
|
406
|
+
public void setMirror(boolean mirror) {
|
|
407
|
+
if (this.mirror != mirror) {
|
|
408
|
+
this.mirror = mirror;
|
|
409
|
+
surfaceViewRenderer.setMirror(mirror);
|
|
410
|
+
// SurfaceViewRenderer takes the value of its mirror property into
|
|
411
|
+
// account upon its layout.
|
|
412
|
+
requestSurfaceViewRendererLayout();
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* In the fashion of
|
|
418
|
+
* https://www.w3.org/TR/html5/embedded-content-0.html#dom-video-videowidth
|
|
419
|
+
* and https://www.w3.org/TR/html5/rendering.html#video-object-fit,
|
|
420
|
+
* resembles the CSS style {@code object-fit}.
|
|
421
|
+
*
|
|
422
|
+
* @param objectFit For details, refer to the documentation of the
|
|
423
|
+
* {@code objectFit} property of the JavaScript counterpart of
|
|
424
|
+
* {@code WebRTCView} i.e. {@code RTCView}.
|
|
425
|
+
*/
|
|
426
|
+
public void setObjectFit(String objectFit) {
|
|
427
|
+
ScalingType scalingType =
|
|
428
|
+
"cover".equals(objectFit) ? ScalingType.SCALE_ASPECT_FILL : ScalingType.SCALE_ASPECT_FIT;
|
|
429
|
+
|
|
430
|
+
setScalingType(scalingType);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
private void setScalingType(ScalingType scalingType) {
|
|
434
|
+
synchronized (layoutSyncRoot) {
|
|
435
|
+
if (this.scalingType == scalingType) {
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
this.scalingType = scalingType;
|
|
439
|
+
surfaceViewRenderer.setScalingType(scalingType);
|
|
440
|
+
}
|
|
441
|
+
// Both this instance ant its SurfaceViewRenderer take the value of
|
|
442
|
+
// their scalingType properties into account upon their layouts.
|
|
443
|
+
requestSurfaceViewRendererLayout();
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Sets the {@code MediaStream} to be rendered by this {@code WebRTCView}.
|
|
448
|
+
* The implementation renders the first {@link VideoTrack}, if any, of the
|
|
449
|
+
* specified {@code mediaStream}.
|
|
450
|
+
*
|
|
451
|
+
* @param streamURL The URL of the {@code MediaStream} to be rendered by
|
|
452
|
+
* this {@code WebRTCView} or {@code null}.
|
|
453
|
+
*/
|
|
454
|
+
void setStreamURL(String streamURL) {
|
|
455
|
+
// Is the value of this.streamURL really changing?
|
|
456
|
+
if (!Objects.equals(streamURL, this.streamURL)) {
|
|
457
|
+
// XXX The value of this.streamURL is really changing. Before
|
|
458
|
+
// realizing/applying the change, let go of the old videoTrack. Of
|
|
459
|
+
// course, that is only necessary if the value of videoTrack will
|
|
460
|
+
// really change. Please note though that letting go of the old
|
|
461
|
+
// videoTrack before assigning to this.streamURL is vital;
|
|
462
|
+
// otherwise, removeRendererFromVideoTrack will fail to remove the
|
|
463
|
+
// old videoTrack from the associated videoRenderer, two
|
|
464
|
+
// VideoTracks (the old and the new) may start rendering and, most
|
|
465
|
+
// importantly the videoRender may eventually crash when the old
|
|
466
|
+
// videoTrack is disposed.
|
|
467
|
+
VideoTrack videoTrack = getVideoTrackForStreamURL(streamURL);
|
|
468
|
+
|
|
469
|
+
if (this.videoTrack != videoTrack) {
|
|
470
|
+
setVideoTrack(null);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
this.streamURL = streamURL;
|
|
474
|
+
|
|
475
|
+
// After realizing/applying the change in the value of
|
|
476
|
+
// this.streamURL, reflect it on the value of videoTrack.
|
|
477
|
+
setVideoTrack(videoTrack);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Sets the {@code VideoTrack} to be rendered by this {@code WebRTCView}.
|
|
483
|
+
*
|
|
484
|
+
* @param videoTrack The {@code VideoTrack} to be rendered by this
|
|
485
|
+
* {@code WebRTCView} or {@code null}.
|
|
486
|
+
*/
|
|
487
|
+
private void setVideoTrack(VideoTrack videoTrack) {
|
|
488
|
+
VideoTrack oldVideoTrack = this.videoTrack;
|
|
489
|
+
|
|
490
|
+
if (oldVideoTrack != videoTrack) {
|
|
491
|
+
if (oldVideoTrack != null) {
|
|
492
|
+
if (videoTrack == null) {
|
|
493
|
+
// If we are not going to render any stream, clean the
|
|
494
|
+
// surface.
|
|
495
|
+
cleanSurfaceViewRenderer();
|
|
496
|
+
}
|
|
497
|
+
removeRendererFromVideoTrack();
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
this.videoTrack = videoTrack;
|
|
501
|
+
|
|
502
|
+
if (videoTrack != null) {
|
|
503
|
+
tryAddRendererToVideoTrack();
|
|
504
|
+
if (oldVideoTrack == null) {
|
|
505
|
+
// If there was no old track, clean the surface so we start
|
|
506
|
+
// with black.
|
|
507
|
+
cleanSurfaceViewRenderer();
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* Sets the z-order of this {@link WebRTCView} in the stacking space of all
|
|
515
|
+
* {@code WebRTCView}s. For more details, refer to the documentation of the
|
|
516
|
+
* {@code zOrder} property of the JavaScript counterpart of
|
|
517
|
+
* {@code WebRTCView} i.e. {@code RTCView}.
|
|
518
|
+
*
|
|
519
|
+
* @param zOrder The z-order to set on this {@code WebRTCView}.
|
|
520
|
+
*/
|
|
521
|
+
public void setZOrder(int zOrder) {
|
|
522
|
+
switch (zOrder) {
|
|
523
|
+
case 0:
|
|
524
|
+
surfaceViewRenderer.setZOrderMediaOverlay(false);
|
|
525
|
+
break;
|
|
526
|
+
case 1:
|
|
527
|
+
surfaceViewRenderer.setZOrderMediaOverlay(true);
|
|
528
|
+
break;
|
|
529
|
+
case 2:
|
|
530
|
+
surfaceViewRenderer.setZOrderOnTop(true);
|
|
531
|
+
break;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* Starts rendering {@link #videoTrack} if rendering is not in progress and
|
|
537
|
+
* all preconditions for the start of rendering are met.
|
|
538
|
+
*/
|
|
539
|
+
private void tryAddRendererToVideoTrack() {
|
|
540
|
+
if (!rendererAttached && videoTrack != null && ViewCompat.isAttachedToWindow(this)) {
|
|
541
|
+
EglBase.Context sharedContext = EglUtils.getRootEglBaseContext();
|
|
542
|
+
|
|
543
|
+
if (sharedContext == null) {
|
|
544
|
+
// If SurfaceViewRenderer#init() is invoked, it will throw a
|
|
545
|
+
// RuntimeException which will very likely kill the application.
|
|
546
|
+
Log.e(TAG, "Failed to render a VideoTrack!");
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
try {
|
|
551
|
+
surfaceViewRenderer.init(sharedContext, rendererEvents);
|
|
552
|
+
surfaceViewRendererInstances++;
|
|
553
|
+
} catch (Exception e) {
|
|
554
|
+
Logging.e(
|
|
555
|
+
TAG, "Failed to initialize surfaceViewRenderer on instance " + surfaceViewRendererInstances, e);
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
560
|
+
try {
|
|
561
|
+
videoTrack.addSink(surfaceViewRenderer);
|
|
562
|
+
} catch (Throwable tr) {
|
|
563
|
+
// XXX If WebRTCModule#mediaStreamTrackRelease has already been
|
|
564
|
+
// invoked on videoTrack, then it is no longer safe to call addSink
|
|
565
|
+
// on the instance, it will throw IllegalStateException.
|
|
566
|
+
|
|
567
|
+
Log.e(TAG, "Failed to add renderer", tr);
|
|
568
|
+
}
|
|
569
|
+
});
|
|
570
|
+
|
|
571
|
+
rendererAttached = true;
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* Sets whether the onDimensionsChange callback should be called.
|
|
577
|
+
*
|
|
578
|
+
* @param enabled Whether the callback should be enabled.
|
|
579
|
+
*/
|
|
580
|
+
public void setOnDimensionsChange(boolean enabled) {
|
|
581
|
+
this.onDimensionsChangeEnabled = enabled;
|
|
582
|
+
}
|
|
583
|
+
}
|