From 8db9a7d145f0e2d915f57ec9048052eb5e92da58 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Sat, 6 Dec 2025 22:25:04 -0800 Subject: [PATCH 01/81] Remove video and audio components from library --- .../webrtc/examples/CodecListExample.java | 121 ---- .../webrtc/examples/DesktopVideoExample.java | 251 ------- .../examples/PeerConnectionExample.java | 283 -------- .../onvoid/webrtc/examples/WhepExample.java | 319 --------- .../examples/util/MediaFrameLogger.java | 113 ---- .../webrtc/examples/web/WebClientExample.java | 246 ------- .../web/connection/PeerConnectionManager.java | 93 --- .../examples/web/media/AudioGenerator.java | 174 ----- .../examples/web/media/MediaManager.java | 275 -------- .../examples/web/media/VideoGenerator.java | 220 ------ .../webrtc/examples/web/server/WebServer.java | 134 ---- .../examples/web/server/WebSocketHandler.java | 173 ----- webrtc-jni/src/main/cpp/CMakeLists.txt | 26 +- .../cpp/dependencies/webrtc/CMakeLists.txt | 23 +- .../macos/patch_for_mac_deviceId.patch | 32 - .../src/main/cpp/include/JNI_AudioConverter.h | 37 - .../main/cpp/include/JNI_AudioDeviceModule.h | 21 - .../cpp/include/JNI_AudioDeviceModuleBase.h | 229 ------- .../main/cpp/include/JNI_AudioProcessing.h | 77 --- .../src/main/cpp/include/JNI_AudioResampler.h | 37 - .../src/main/cpp/include/JNI_AudioTrack.h | 37 - .../main/cpp/include/JNI_CustomAudioSource.h | 45 -- .../main/cpp/include/JNI_CustomVideoSource.h | 45 -- .../main/cpp/include/JNI_DesktopCapturer.h | 69 -- .../include/JNI_HeadlessAudioDeviceModule.h | 22 - .../src/main/cpp/include/JNI_MediaDevices.h | 77 --- .../src/main/cpp/include/JNI_MediaSource.h | 21 - .../src/main/cpp/include/JNI_MediaStream.h | 61 -- .../main/cpp/include/JNI_MediaStreamTrack.h | 93 --- .../main/cpp/include/JNI_NativeI420Buffer.h | 37 - .../cpp/include/JNI_PeerConnectionFactory.h | 39 -- .../main/cpp/include/JNI_PowerManagement.h | 29 - .../src/main/cpp/include/JNI_RTCDtmfSender.h | 69 -- .../main/cpp/include/JNI_RTCPeerConnection.h | 63 -- .../src/main/cpp/include/JNI_RTCRtpReceiver.h | 53 -- .../src/main/cpp/include/JNI_RTCRtpSender.h | 69 -- .../main/cpp/include/JNI_RTCRtpTransceiver.h | 93 --- .../src/main/cpp/include/JNI_ScreenCapturer.h | 21 - .../src/main/cpp/include/JNI_SyncClock.h | 53 -- .../cpp/include/JNI_VideoBufferConverter.h | 45 -- .../src/main/cpp/include/JNI_VideoCapture.h | 69 -- .../main/cpp/include/JNI_VideoDesktopSource.h | 77 --- .../main/cpp/include/JNI_VideoDeviceSource.h | 61 -- .../src/main/cpp/include/JNI_VideoTrack.h | 29 - .../cpp/include/JNI_VoiceActivityDetector.h | 45 -- webrtc-jni/src/main/cpp/include/JNI_WebRTC.h | 4 - .../src/main/cpp/include/JNI_WindowCapturer.h | 21 - .../src/main/cpp/include/WebRTCContext.h | 45 +- .../src/main/cpp/include/api/AudioOptions.h | 49 -- .../src/main/cpp/include/api/AudioTrackSink.h | 54 -- .../include/api/HeadlessAudioDeviceModule.h | 181 ----- .../cpp/include/api/PeerConnectionObserver.h | 6 - .../src/main/cpp/include/api/RTCDtmfSender.h | 44 -- .../cpp/include/api/RTCDtmfSenderObserver.h | 55 -- .../main/cpp/include/api/RTCRtcpParameters.h | 47 -- .../main/cpp/include/api/RTCRtpCapabilities.h | 44 -- .../cpp/include/api/RTCRtpCodecCapability.h | 50 -- .../cpp/include/api/RTCRtpCodecParameters.h | 51 -- .../include/api/RTCRtpContributingSource.h | 50 -- .../include/api/RTCRtpEncodingParameters.h | 51 -- .../cpp/include/api/RTCRtpHeaderExtension.h | 48 -- .../api/RTCRtpHeaderExtensionCapability.h | 44 -- .../main/cpp/include/api/RTCRtpParameters.h | 48 -- .../cpp/include/api/RTCRtpSendParameters.h | 47 -- .../include/api/RTCRtpSynchronizationSource.h | 46 -- .../cpp/include/api/RTCRtpTransceiverInit.h | 46 -- .../src/main/cpp/include/api/VideoFrame.h | 70 -- .../src/main/cpp/include/api/VideoTrackSink.h | 58 -- .../src/main/cpp/include/media/Device.h | 98 --- .../cpp/include/media/DeviceChangeListener.h | 58 -- .../cpp/include/media/DeviceHotplugListener.h | 42 -- .../src/main/cpp/include/media/DeviceList.h | 117 ---- .../main/cpp/include/media/DeviceManager.h | 55 -- .../include/media/MediaStreamTrackObserver.h | 66 -- .../src/main/cpp/include/media/SyncClock.h | 46 -- .../cpp/include/media/audio/AudioConverter.h | 57 -- .../cpp/include/media/audio/AudioDevice.h | 66 -- .../include/media/audio/AudioDeviceManager.h | 64 -- .../cpp/include/media/audio/AudioProcessing.h | 44 -- .../media/audio/AudioProcessingConfig.h | 207 ------ .../media/audio/AudioProcessingStats.h | 49 -- .../media/audio/AudioProcessingStreamConfig.h | 46 -- .../main/cpp/include/media/audio/AudioSink.h | 56 -- .../cpp/include/media/audio/AudioSource.h | 55 -- .../include/media/audio/AudioTransportSink.h | 64 -- .../media/audio/AudioTransportSource.h | 63 -- .../include/media/audio/CustomAudioSource.h | 61 -- .../include/media/audio/RawAudioFileSink.h | 51 -- .../include/media/audio/RawAudioFileSource.h | 50 -- .../include/media/audio/WavAudioFileSink.h | 60 -- .../include/media/audio/WavAudioFileSource.h | 58 -- .../audio/linux/PulseAudioDeviceManager.h | 78 --- .../media/audio/linux/PulseAudioLoader.h | 164 ----- .../audio/macos/CoreAudioDeviceManager.h | 59 -- .../audio/windows/WindowsAudioDeviceManager.h | 72 -- .../include/media/video/CustomVideoSource.h | 49 -- .../include/media/video/RawVideoFileSink.h | 42 -- .../cpp/include/media/video/VideoCapture.h | 42 -- .../include/media/video/VideoCaptureBase.h | 48 -- .../media/video/VideoCaptureCapability.h | 53 -- .../cpp/include/media/video/VideoDevice.h | 59 -- .../include/media/video/VideoDeviceManager.h | 62 -- .../main/cpp/include/media/video/VideoSink.h | 32 - .../media/video/VideoTrackDesktopSource.h | 75 --- .../media/video/VideoTrackDeviceSource.h | 66 -- .../media/video/VideoTrackDeviceSourceBase.h | 44 -- .../video/desktop/DesktopCaptureCallback.h | 59 -- .../media/video/desktop/DesktopCapturer.h | 61 -- .../media/video/desktop/DesktopFrame.h | 45 -- .../media/video/desktop/DesktopSource.h | 48 -- .../media/video/desktop/PowerManagement.h | 36 - .../desktop/linux/LinuxPowerManagement.h | 51 -- .../desktop/macos/MacOSPowerManagement.h | 43 -- .../desktop/windows/WindowsPowerManagement.h | 38 -- .../video/linux/V4l2VideoDeviceManager.h | 60 -- .../media/video/macos/AVFVideoDeviceManager.h | 53 -- .../media/video/macos/VideoCaptureMac.h | 54 -- .../video/macos/VideoTrackDeviceSourceMac.h | 66 -- .../video/windows/WindowsVideoDeviceManager.h | 49 -- .../cpp/include/platform/macos/MacUtils.h | 46 -- .../include/platform/windows/ComInitializer.h | 35 - .../cpp/include/platform/windows/ComPtr.h | 152 ----- .../include/platform/windows/MFInitializer.h | 37 - .../cpp/include/platform/windows/MFUtils.h | 40 -- .../platform/windows/WinHotplugNotifier.h | 64 -- .../cpp/include/platform/windows/WinUtils.h | 135 ---- .../src/main/cpp/src/JNI_AudioConverter.cpp | 66 -- .../main/cpp/src/JNI_AudioDeviceModule.cpp | 47 -- .../cpp/src/JNI_AudioDeviceModuleBase.cpp | 473 ------------- .../src/main/cpp/src/JNI_AudioProcessing.cpp | 220 ------ .../src/main/cpp/src/JNI_AudioResampler.cpp | 81 --- .../src/main/cpp/src/JNI_AudioTrack.cpp | 68 -- .../main/cpp/src/JNI_CustomAudioSource.cpp | 76 --- .../main/cpp/src/JNI_CustomVideoSource.cpp | 75 --- .../src/main/cpp/src/JNI_DesktopCapturer.cpp | 132 ---- .../cpp/src/JNI_HeadlessAudioDeviceModule.cpp | 44 -- .../src/main/cpp/src/JNI_MediaDevices.cpp | 193 ------ .../src/main/cpp/src/JNI_MediaSource.cpp | 30 - .../src/main/cpp/src/JNI_MediaStream.cpp | 121 ---- .../src/main/cpp/src/JNI_MediaStreamTrack.cpp | 164 ----- .../src/main/cpp/src/JNI_NativeI420Buffer.cpp | 80 --- .../cpp/src/JNI_PeerConnectionFactory.cpp | 225 ++----- .../src/main/cpp/src/JNI_PowerManagement.cpp | 48 -- .../src/main/cpp/src/JNI_RTCDtmfSender.cpp | 87 --- .../main/cpp/src/JNI_RTCPeerConnection.cpp | 140 ---- .../src/main/cpp/src/JNI_RTCRtpReceiver.cpp | 99 --- .../src/main/cpp/src/JNI_RTCRtpSender.cpp | 123 ---- .../main/cpp/src/JNI_RTCRtpTransceiver.cpp | 153 ----- .../src/main/cpp/src/JNI_ScreenCapturer.cpp | 25 - webrtc-jni/src/main/cpp/src/JNI_SyncClock.cpp | 66 -- .../main/cpp/src/JNI_VideoBufferConverter.cpp | 202 ------ .../src/main/cpp/src/JNI_VideoCapture.cpp | 130 ---- .../main/cpp/src/JNI_VideoDesktopSource.cpp | 114 ---- .../main/cpp/src/JNI_VideoDeviceSource.cpp | 151 ----- .../src/main/cpp/src/JNI_VideoTrack.cpp | 55 -- .../cpp/src/JNI_VoiceActivityDetector.cpp | 64 -- .../src/main/cpp/src/JNI_WindowCapturer.cpp | 25 - webrtc-jni/src/main/cpp/src/WebRTCContext.cpp | 116 +--- .../src/main/cpp/src/api/AudioOptions.cpp | 52 -- .../src/main/cpp/src/api/AudioTrackSink.cpp | 50 -- .../cpp/src/api/HeadlessAudioDeviceModule.cpp | 637 ------------------ .../cpp/src/api/PeerConnectionObserver.cpp | 45 -- .../src/main/cpp/src/api/RTCDtmfSender.cpp | 43 -- .../cpp/src/api/RTCDtmfSenderObserver.cpp | 49 -- .../main/cpp/src/api/RTCRtcpParameters.cpp | 67 -- .../main/cpp/src/api/RTCRtpCapabilities.cpp | 50 -- .../cpp/src/api/RTCRtpCodecCapability.cpp | 109 --- .../cpp/src/api/RTCRtpCodecParameters.cpp | 107 --- .../cpp/src/api/RTCRtpContributingSource.cpp | 73 -- .../cpp/src/api/RTCRtpEncodingParameters.cpp | 106 --- .../cpp/src/api/RTCRtpHeaderExtension.cpp | 67 -- .../api/RTCRtpHeaderExtensionCapability.cpp | 47 -- .../src/main/cpp/src/api/RTCRtpParameters.cpp | 75 --- .../main/cpp/src/api/RTCRtpSendParameters.cpp | 98 --- .../src/api/RTCRtpSynchronizationSource.cpp | 72 -- .../cpp/src/api/RTCRtpTransceiverInit.cpp | 57 -- .../src/main/cpp/src/api/VideoFrame.cpp | 125 ---- .../src/main/cpp/src/api/VideoTrackSink.cpp | 66 -- webrtc-jni/src/main/cpp/src/media/Device.cpp | 112 --- .../cpp/src/media/DeviceChangeListener.cpp | 76 --- .../src/main/cpp/src/media/DeviceManager.cpp | 66 -- .../src/media/MediaStreamTrackObserver.cpp | 80 --- .../src/main/cpp/src/media/SyncClock.cpp | 42 -- .../cpp/src/media/audio/AudioConverter.cpp | 200 ------ .../main/cpp/src/media/audio/AudioDevice.cpp | 71 -- .../src/media/audio/AudioDeviceManager.cpp | 82 --- .../cpp/src/media/audio/AudioProcessing.cpp | 54 -- .../src/media/audio/AudioProcessingConfig.cpp | 303 --------- .../src/media/audio/AudioProcessingStats.cpp | 42 -- .../audio/AudioProcessingStreamConfig.cpp | 47 -- .../src/media/audio/AudioTransportSink.cpp | 61 -- .../src/media/audio/AudioTransportSource.cpp | 76 --- .../cpp/src/media/audio/CustomAudioSource.cpp | 82 --- .../cpp/src/media/audio/RawAudioFileSink.cpp | 52 -- .../src/media/audio/RawAudioFileSource.cpp | 72 -- .../cpp/src/media/audio/WavAudioFileSink.cpp | 46 -- .../src/media/audio/WavAudioFileSource.cpp | 64 -- .../audio/linux/PulseAudioDeviceManager.cpp | 438 ------------ .../audio/macos/CoreAudioDeviceManager.cpp | 480 ------------- .../windows/WindowsAudioDeviceManager.cpp | 488 -------------- .../cpp/src/media/video/CustomVideoSource.cpp | 68 -- .../cpp/src/media/video/RawVideoFileSink.cpp | 45 -- .../main/cpp/src/media/video/VideoCapture.cpp | 115 ---- .../cpp/src/media/video/VideoCaptureBase.cpp | 46 -- .../media/video/VideoCaptureCapability.cpp | 64 -- .../main/cpp/src/media/video/VideoDevice.cpp | 68 -- .../src/media/video/VideoDeviceManager.cpp | 54 -- .../media/video/VideoTrackDesktopSource.cpp | 294 -------- .../media/video/VideoTrackDeviceSource.cpp | 209 ------ .../video/VideoTrackDeviceSourceBase.cpp | 41 -- .../video/desktop/DesktopCaptureCallback.cpp | 117 ---- .../media/video/desktop/DesktopCapturer.cpp | 111 --- .../src/media/video/desktop/DesktopFrame.cpp | 57 -- .../src/media/video/desktop/DesktopSource.cpp | 61 -- .../desktop/linux/LinuxPowerManagement.cpp | 128 ---- .../desktop/macos/MacOSPowerManagement.cpp | 45 -- .../windows/WindowsPowerManagement.cpp | 39 -- .../video/linux/V4l2VideoDeviceManager.cpp | 331 --------- .../video/macos/AVFVideoDeviceManager.cpp | 219 ------ .../src/media/video/macos/VideoCaptureMac.cpp | 162 ----- .../video/macos/VideoTrackDeviceSourceMac.cpp | 214 ------ .../windows/WindowsVideoDeviceManager.cpp | 144 ---- .../main/cpp/src/platform/macos/MacUtils.cpp | 54 -- .../src/platform/windows/ComInitializer.cpp | 46 -- .../src/platform/windows/MFInitializer.cpp | 43 -- .../main/cpp/src/platform/windows/MFUtils.cpp | 91 --- .../platform/windows/WinHotplugNotifier.cpp | 224 ------ webrtc/pom.xml | 3 - .../onvoid/webrtc/PeerConnectionFactory.java | 105 +-- .../onvoid/webrtc/PeerConnectionObserver.java | 60 -- .../dev/onvoid/webrtc/RTCDtlsTransport.java | 4 +- .../java/dev/onvoid/webrtc/RTCDtmfSender.java | 145 ---- .../onvoid/webrtc/RTCDtmfSenderObserver.java | 42 -- .../dev/onvoid/webrtc/RTCIceTransport.java | 4 +- .../dev/onvoid/webrtc/RTCPeerConnection.java | 96 +-- .../dev/onvoid/webrtc/RTCRtcpParameters.java | 55 -- .../dev/onvoid/webrtc/RTCRtpCapabilities.java | 80 --- .../onvoid/webrtc/RTCRtpCodecCapability.java | 146 ---- .../onvoid/webrtc/RTCRtpCodecParameters.java | 92 --- .../webrtc/RTCRtpContributingSource.java | 70 -- .../webrtc/RTCRtpEncodingParameters.java | 87 --- .../RTCRtpHeaderExtensionCapability.java | 56 -- .../RTCRtpHeaderExtensionParameters.java | 64 -- .../dev/onvoid/webrtc/RTCRtpParameters.java | 56 -- .../dev/onvoid/webrtc/RTCRtpReceiver.java | 86 --- .../onvoid/webrtc/RTCRtpSendParameters.java | 47 -- .../java/dev/onvoid/webrtc/RTCRtpSender.java | 115 ---- .../webrtc/RTCRtpSynchronizationSource.java | 56 -- .../dev/onvoid/webrtc/RTCRtpTransceiver.java | 142 ---- .../webrtc/RTCRtpTransceiverDirection.java | 72 -- .../onvoid/webrtc/RTCRtpTransceiverInit.java | 56 -- .../media/AudioDeviceDirectionType.java | 7 - .../java/dev/onvoid/webrtc/media/Device.java | 77 --- .../webrtc/media/DeviceChangeListener.java | 41 -- .../onvoid/webrtc/media/DeviceFormFactor.java | 9 - .../onvoid/webrtc/media/DeviceTransport.java | 8 - .../java/dev/onvoid/webrtc/media/FourCC.java | 79 --- .../dev/onvoid/webrtc/media/MediaDevices.java | 54 -- .../dev/onvoid/webrtc/media/MediaSource.java | 43 -- .../dev/onvoid/webrtc/media/MediaStream.java | 77 --- .../onvoid/webrtc/media/MediaStreamTrack.java | 142 ---- .../media/MediaStreamTrackEndedListener.java | 35 - .../media/MediaStreamTrackMuteListener.java | 36 - .../webrtc/media/MediaStreamTrackState.java | 35 - .../dev/onvoid/webrtc/media/MediaType.java | 36 - .../dev/onvoid/webrtc/media/SyncClock.java | 71 -- .../webrtc/media/audio/AudioConverter.java | 106 --- .../webrtc/media/audio/AudioDevice.java | 34 - .../webrtc/media/audio/AudioDeviceModule.java | 50 -- .../media/audio/AudioDeviceModuleBase.java | 318 --------- .../onvoid/webrtc/media/audio/AudioLayer.java | 61 -- .../webrtc/media/audio/AudioOptions.java | 59 -- .../webrtc/media/audio/AudioPlayer.java | 103 --- .../webrtc/media/audio/AudioProcessing.java | 166 ----- .../media/audio/AudioProcessingConfig.java | 513 -------------- .../media/audio/AudioProcessingStats.java | 75 --- .../audio/AudioProcessingStreamConfig.java | 31 - .../webrtc/media/audio/AudioRecorder.java | 91 --- .../webrtc/media/audio/AudioResampler.java | 98 --- .../onvoid/webrtc/media/audio/AudioSink.java | 24 - .../webrtc/media/audio/AudioSource.java | 24 - .../onvoid/webrtc/media/audio/AudioTrack.java | 92 --- .../webrtc/media/audio/AudioTrackSink.java | 23 - .../webrtc/media/audio/AudioTrackSource.java | 32 - .../webrtc/media/audio/CustomAudioSource.java | 80 --- .../audio/HeadlessAudioDeviceModule.java | 40 -- .../media/audio/VoiceActivityDetector.java | 66 -- .../webrtc/media/video/CustomVideoSource.java | 75 --- .../onvoid/webrtc/media/video/FramePacer.java | 86 --- .../onvoid/webrtc/media/video/I420Buffer.java | 56 -- .../webrtc/media/video/NativeI420Buffer.java | 203 ------ .../media/video/VideoBufferConverter.java | 237 ------- .../webrtc/media/video/VideoCapture.java | 139 ---- .../media/video/VideoCaptureCapability.java | 62 -- .../media/video/VideoDesktopSource.java | 41 -- .../webrtc/media/video/VideoDevice.java | 27 - .../webrtc/media/video/VideoDeviceSource.java | 39 -- .../onvoid/webrtc/media/video/VideoFrame.java | 104 --- .../webrtc/media/video/VideoFrameBuffer.java | 48 -- .../onvoid/webrtc/media/video/VideoTrack.java | 86 --- .../webrtc/media/video/VideoTrackSink.java | 23 - .../webrtc/media/video/VideoTrackSource.java | 30 - .../video/desktop/DesktopCaptureCallback.java | 37 - .../media/video/desktop/DesktopCapturer.java | 125 ---- .../media/video/desktop/DesktopFrame.java | 75 --- .../media/video/desktop/DesktopSource.java | 71 -- .../video/desktop/DesktopSourceType.java | 33 - .../media/video/desktop/PowerManagement.java | 36 - .../media/video/desktop/ScreenCapturer.java | 38 -- .../media/video/desktop/WindowCapturer.java | 39 -- webrtc/src/main/java/module-info.java | 6 +- .../META-INF/native-image/jni-config.json | 67 -- .../META-INF/native-image/reflect-config.json | 96 --- .../webrtc/PeerConnectionFactoryTests.java | 133 ---- .../dev/onvoid/webrtc/RTCDtmfSenderTests.java | 197 ------ .../onvoid/webrtc/RTCPeerConnectionTests.java | 162 ----- .../onvoid/webrtc/RTCRtpTransceiverTests.java | 61 -- .../test/java/dev/onvoid/webrtc/TestBase.java | 9 +- .../onvoid/webrtc/logging/LoggingTests.java | 6 +- .../onvoid/webrtc/media/MediaSourceTests.java | 37 - .../media/audio/AudioConverterTest.java | 129 ---- .../media/audio/AudioDeviceModuleTest.java | 48 -- .../media/audio/AudioProcessingTest.java | 317 --------- .../media/audio/AudioResamplerTest.java | 122 ---- .../webrtc/media/audio/AudioTrackTests.java | 74 -- .../media/audio/CustomAudioSourceTest.java | 167 ----- .../audio/DummyAudioDeviceModuleTest.java | 44 -- .../audio/HeadlessADMIntegrationTest.java | 267 -------- .../webrtc/media/audio/HeadlessADMTest.java | 111 --- .../audio/VoiceActivityDetectorTest.java | 79 --- .../media/video/CustomVideoSourceTest.java | 188 ------ .../media/video/VideoBufferConverterTest.java | 347 ---------- .../webrtc/media/video/VideoTrackTests.java | 73 -- 333 files changed, 79 insertions(+), 29773 deletions(-) delete mode 100644 webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/CodecListExample.java delete mode 100644 webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/DesktopVideoExample.java delete mode 100644 webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/PeerConnectionExample.java delete mode 100644 webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/WhepExample.java delete mode 100644 webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/util/MediaFrameLogger.java delete mode 100644 webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/WebClientExample.java delete mode 100644 webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/media/AudioGenerator.java delete mode 100644 webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/media/MediaManager.java delete mode 100644 webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/media/VideoGenerator.java delete mode 100644 webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/server/WebServer.java delete mode 100644 webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/server/WebSocketHandler.java delete mode 100644 webrtc-jni/src/main/cpp/dependencies/webrtc/patches/macos/patch_for_mac_deviceId.patch delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_AudioConverter.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_AudioDeviceModule.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_AudioDeviceModuleBase.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_AudioProcessing.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_AudioResampler.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_AudioTrack.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_CustomAudioSource.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_CustomVideoSource.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_DesktopCapturer.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_HeadlessAudioDeviceModule.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_MediaDevices.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_MediaSource.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_MediaStream.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_MediaStreamTrack.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_NativeI420Buffer.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_PowerManagement.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_RTCDtmfSender.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_RTCRtpReceiver.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_RTCRtpSender.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_RTCRtpTransceiver.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_ScreenCapturer.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_SyncClock.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_VideoBufferConverter.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_VideoCapture.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_VideoDesktopSource.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_VideoDeviceSource.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_VideoTrack.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_VoiceActivityDetector.h delete mode 100644 webrtc-jni/src/main/cpp/include/JNI_WindowCapturer.h delete mode 100644 webrtc-jni/src/main/cpp/include/api/AudioOptions.h delete mode 100644 webrtc-jni/src/main/cpp/include/api/AudioTrackSink.h delete mode 100644 webrtc-jni/src/main/cpp/include/api/HeadlessAudioDeviceModule.h delete mode 100644 webrtc-jni/src/main/cpp/include/api/RTCDtmfSender.h delete mode 100644 webrtc-jni/src/main/cpp/include/api/RTCDtmfSenderObserver.h delete mode 100644 webrtc-jni/src/main/cpp/include/api/RTCRtcpParameters.h delete mode 100644 webrtc-jni/src/main/cpp/include/api/RTCRtpCapabilities.h delete mode 100644 webrtc-jni/src/main/cpp/include/api/RTCRtpCodecCapability.h delete mode 100644 webrtc-jni/src/main/cpp/include/api/RTCRtpCodecParameters.h delete mode 100644 webrtc-jni/src/main/cpp/include/api/RTCRtpContributingSource.h delete mode 100644 webrtc-jni/src/main/cpp/include/api/RTCRtpEncodingParameters.h delete mode 100644 webrtc-jni/src/main/cpp/include/api/RTCRtpHeaderExtension.h delete mode 100644 webrtc-jni/src/main/cpp/include/api/RTCRtpHeaderExtensionCapability.h delete mode 100644 webrtc-jni/src/main/cpp/include/api/RTCRtpParameters.h delete mode 100644 webrtc-jni/src/main/cpp/include/api/RTCRtpSendParameters.h delete mode 100644 webrtc-jni/src/main/cpp/include/api/RTCRtpSynchronizationSource.h delete mode 100644 webrtc-jni/src/main/cpp/include/api/RTCRtpTransceiverInit.h delete mode 100644 webrtc-jni/src/main/cpp/include/api/VideoFrame.h delete mode 100644 webrtc-jni/src/main/cpp/include/api/VideoTrackSink.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/Device.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/DeviceChangeListener.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/DeviceHotplugListener.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/DeviceList.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/DeviceManager.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/MediaStreamTrackObserver.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/SyncClock.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/audio/AudioConverter.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/audio/AudioDevice.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/audio/AudioDeviceManager.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/audio/AudioProcessing.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/audio/AudioProcessingConfig.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/audio/AudioProcessingStats.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/audio/AudioProcessingStreamConfig.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/audio/AudioSink.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/audio/AudioSource.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/audio/AudioTransportSink.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/audio/AudioTransportSource.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/audio/CustomAudioSource.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/audio/RawAudioFileSink.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/audio/RawAudioFileSource.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/audio/WavAudioFileSink.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/audio/WavAudioFileSource.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/audio/linux/PulseAudioDeviceManager.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/audio/linux/PulseAudioLoader.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/audio/macos/CoreAudioDeviceManager.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/audio/windows/WindowsAudioDeviceManager.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/video/CustomVideoSource.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/video/RawVideoFileSink.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/video/VideoCapture.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/video/VideoCaptureBase.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/video/VideoCaptureCapability.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/video/VideoDevice.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/video/VideoDeviceManager.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/video/VideoSink.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/video/VideoTrackDesktopSource.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/video/VideoTrackDeviceSource.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/video/VideoTrackDeviceSourceBase.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/video/desktop/DesktopCaptureCallback.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/video/desktop/DesktopCapturer.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/video/desktop/DesktopFrame.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/video/desktop/DesktopSource.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/video/desktop/PowerManagement.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/video/desktop/linux/LinuxPowerManagement.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/video/desktop/macos/MacOSPowerManagement.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/video/desktop/windows/WindowsPowerManagement.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/video/linux/V4l2VideoDeviceManager.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/video/macos/AVFVideoDeviceManager.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/video/macos/VideoCaptureMac.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/video/macos/VideoTrackDeviceSourceMac.h delete mode 100644 webrtc-jni/src/main/cpp/include/media/video/windows/WindowsVideoDeviceManager.h delete mode 100644 webrtc-jni/src/main/cpp/include/platform/macos/MacUtils.h delete mode 100644 webrtc-jni/src/main/cpp/include/platform/windows/ComInitializer.h delete mode 100644 webrtc-jni/src/main/cpp/include/platform/windows/ComPtr.h delete mode 100644 webrtc-jni/src/main/cpp/include/platform/windows/MFInitializer.h delete mode 100644 webrtc-jni/src/main/cpp/include/platform/windows/MFUtils.h delete mode 100644 webrtc-jni/src/main/cpp/include/platform/windows/WinHotplugNotifier.h delete mode 100644 webrtc-jni/src/main/cpp/include/platform/windows/WinUtils.h delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_AudioConverter.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_AudioDeviceModule.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_AudioDeviceModuleBase.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_AudioProcessing.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_AudioResampler.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_AudioTrack.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_CustomAudioSource.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_CustomVideoSource.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_DesktopCapturer.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_HeadlessAudioDeviceModule.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_MediaDevices.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_MediaSource.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_MediaStream.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_MediaStreamTrack.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_NativeI420Buffer.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_PowerManagement.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_RTCDtmfSender.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_RTCRtpReceiver.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_RTCRtpSender.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_RTCRtpTransceiver.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_ScreenCapturer.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_SyncClock.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_VideoBufferConverter.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_VideoCapture.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_VideoDesktopSource.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_VideoDeviceSource.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_VideoTrack.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_VoiceActivityDetector.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/JNI_WindowCapturer.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/api/AudioOptions.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/api/AudioTrackSink.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/api/HeadlessAudioDeviceModule.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/api/RTCDtmfSender.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/api/RTCDtmfSenderObserver.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/api/RTCRtcpParameters.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/api/RTCRtpCapabilities.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/api/RTCRtpCodecCapability.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/api/RTCRtpCodecParameters.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/api/RTCRtpContributingSource.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/api/RTCRtpEncodingParameters.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/api/RTCRtpHeaderExtension.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/api/RTCRtpHeaderExtensionCapability.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/api/RTCRtpParameters.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/api/RTCRtpSendParameters.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/api/RTCRtpSynchronizationSource.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/api/RTCRtpTransceiverInit.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/api/VideoFrame.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/api/VideoTrackSink.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/Device.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/DeviceChangeListener.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/DeviceManager.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/MediaStreamTrackObserver.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/SyncClock.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/audio/AudioConverter.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/audio/AudioDevice.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/audio/AudioDeviceManager.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/audio/AudioProcessing.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/audio/AudioProcessingConfig.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/audio/AudioProcessingStats.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/audio/AudioProcessingStreamConfig.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/audio/AudioTransportSink.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/audio/AudioTransportSource.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/audio/CustomAudioSource.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/audio/RawAudioFileSink.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/audio/RawAudioFileSource.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/audio/WavAudioFileSink.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/audio/WavAudioFileSource.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/audio/linux/PulseAudioDeviceManager.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/audio/macos/CoreAudioDeviceManager.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/audio/windows/WindowsAudioDeviceManager.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/video/CustomVideoSource.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/video/RawVideoFileSink.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/video/VideoCapture.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/video/VideoCaptureBase.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/video/VideoCaptureCapability.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/video/VideoDevice.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/video/VideoDeviceManager.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/video/VideoTrackDesktopSource.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/video/VideoTrackDeviceSource.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/video/VideoTrackDeviceSourceBase.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/video/desktop/DesktopCaptureCallback.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/video/desktop/DesktopCapturer.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/video/desktop/DesktopFrame.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/video/desktop/DesktopSource.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/video/desktop/linux/LinuxPowerManagement.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/video/desktop/macos/MacOSPowerManagement.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/video/desktop/windows/WindowsPowerManagement.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/video/linux/V4l2VideoDeviceManager.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/video/macos/AVFVideoDeviceManager.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/video/macos/VideoCaptureMac.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/video/macos/VideoTrackDeviceSourceMac.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/media/video/windows/WindowsVideoDeviceManager.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/platform/macos/MacUtils.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/platform/windows/ComInitializer.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/platform/windows/MFInitializer.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/platform/windows/MFUtils.cpp delete mode 100644 webrtc-jni/src/main/cpp/src/platform/windows/WinHotplugNotifier.cpp delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/RTCDtmfSender.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/RTCDtmfSenderObserver.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/RTCRtcpParameters.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpCapabilities.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpCodecCapability.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpCodecParameters.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpContributingSource.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpEncodingParameters.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpHeaderExtensionCapability.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpHeaderExtensionParameters.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpParameters.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpReceiver.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpSendParameters.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpSender.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpSynchronizationSource.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpTransceiver.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpTransceiverDirection.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpTransceiverInit.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/AudioDeviceDirectionType.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/Device.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/DeviceChangeListener.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/DeviceFormFactor.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/DeviceTransport.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/FourCC.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/MediaDevices.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/MediaSource.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/MediaStream.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/MediaStreamTrack.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/MediaStreamTrackEndedListener.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/MediaStreamTrackMuteListener.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/MediaStreamTrackState.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/MediaType.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/SyncClock.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioConverter.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioDevice.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioDeviceModule.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioDeviceModuleBase.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioLayer.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioOptions.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioPlayer.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioProcessing.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioProcessingConfig.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioProcessingStats.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioProcessingStreamConfig.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioRecorder.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioResampler.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioSink.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioSource.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioTrack.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioTrackSink.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioTrackSource.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/audio/CustomAudioSource.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/audio/HeadlessAudioDeviceModule.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/audio/VoiceActivityDetector.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/video/CustomVideoSource.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/video/FramePacer.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/video/I420Buffer.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/video/NativeI420Buffer.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoBufferConverter.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoCapture.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoCaptureCapability.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoDesktopSource.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoDevice.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoDeviceSource.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoFrame.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoFrameBuffer.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoTrack.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoTrackSink.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoTrackSource.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/DesktopCaptureCallback.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/DesktopCapturer.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/DesktopFrame.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/DesktopSource.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/DesktopSourceType.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/PowerManagement.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/ScreenCapturer.java delete mode 100644 webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/WindowCapturer.java delete mode 100644 webrtc/src/test/java/dev/onvoid/webrtc/RTCDtmfSenderTests.java delete mode 100644 webrtc/src/test/java/dev/onvoid/webrtc/RTCRtpTransceiverTests.java delete mode 100644 webrtc/src/test/java/dev/onvoid/webrtc/media/MediaSourceTests.java delete mode 100644 webrtc/src/test/java/dev/onvoid/webrtc/media/audio/AudioConverterTest.java delete mode 100644 webrtc/src/test/java/dev/onvoid/webrtc/media/audio/AudioDeviceModuleTest.java delete mode 100644 webrtc/src/test/java/dev/onvoid/webrtc/media/audio/AudioProcessingTest.java delete mode 100644 webrtc/src/test/java/dev/onvoid/webrtc/media/audio/AudioResamplerTest.java delete mode 100644 webrtc/src/test/java/dev/onvoid/webrtc/media/audio/AudioTrackTests.java delete mode 100644 webrtc/src/test/java/dev/onvoid/webrtc/media/audio/CustomAudioSourceTest.java delete mode 100644 webrtc/src/test/java/dev/onvoid/webrtc/media/audio/DummyAudioDeviceModuleTest.java delete mode 100644 webrtc/src/test/java/dev/onvoid/webrtc/media/audio/HeadlessADMIntegrationTest.java delete mode 100644 webrtc/src/test/java/dev/onvoid/webrtc/media/audio/HeadlessADMTest.java delete mode 100644 webrtc/src/test/java/dev/onvoid/webrtc/media/audio/VoiceActivityDetectorTest.java delete mode 100644 webrtc/src/test/java/dev/onvoid/webrtc/media/video/CustomVideoSourceTest.java delete mode 100644 webrtc/src/test/java/dev/onvoid/webrtc/media/video/VideoBufferConverterTest.java delete mode 100644 webrtc/src/test/java/dev/onvoid/webrtc/media/video/VideoTrackTests.java diff --git a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/CodecListExample.java b/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/CodecListExample.java deleted file mode 100644 index 8722551..0000000 --- a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/CodecListExample.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2025 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.examples; - -import java.util.List; -import java.util.Map; - -import dev.onvoid.webrtc.PeerConnectionFactory; -import dev.onvoid.webrtc.RTCRtpCapabilities; -import dev.onvoid.webrtc.RTCRtpCodecCapability; -import dev.onvoid.webrtc.media.MediaType; - -/** - * Example demonstrating how to list all supported codecs with the WebRTC peer-connection-factory. - *

- * This example shows how to: - *

- * - * @author Alex Andres - */ -public class CodecListExample { - - public static void main(String[] args) { - PeerConnectionFactory factory = new PeerConnectionFactory(); - - try { - // Get receiver capabilities for audio and video. - System.out.println("\nRECEIVER CAPABILITIES:"); - System.out.println("---------------------"); - - System.out.println("\nAudio Receiver Codecs:"); - RTCRtpCapabilities audioReceiverCapabilities = factory.getRtpReceiverCapabilities(MediaType.AUDIO); - printCodecInfo(audioReceiverCapabilities.getCodecs()); - - System.out.println("\nVideo Receiver Codecs:"); - RTCRtpCapabilities videoReceiverCapabilities = factory.getRtpReceiverCapabilities(MediaType.VIDEO); - printCodecInfo(videoReceiverCapabilities.getCodecs()); - - // Get sender capabilities for audio and video. - System.out.println("\nSENDER CAPABILITIES:"); - System.out.println("-------------------"); - - System.out.println("\nAudio Sender Codecs:"); - RTCRtpCapabilities audioSenderCapabilities = factory.getRtpSenderCapabilities(MediaType.AUDIO); - printCodecInfo(audioSenderCapabilities.getCodecs()); - - System.out.println("\nVideo Sender Codecs:"); - RTCRtpCapabilities videoSenderCapabilities = factory.getRtpSenderCapabilities(MediaType.VIDEO); - printCodecInfo(videoSenderCapabilities.getCodecs()); - } - finally { - // Dispose the factory when done. - factory.dispose(); - } - } - - /** - * Prints detailed information about each codec in the provided list. - * All information for a codec is printed in a single line for conciseness. - * - * @param codecs List of codec capabilities to display. - */ - private static void printCodecInfo(List codecs) { - if (codecs.isEmpty()) { - System.out.println(" No codecs found."); - return; - } - - for (int i = 0; i < codecs.size(); i++) { - RTCRtpCodecCapability codec = codecs.get(i); - StringBuilder sb = new StringBuilder(); - - sb.append(" Codec #").append(i + 1).append(": "); - sb.append("MIME Type: ").append(codec.getMimeType()).append(" | "); - sb.append("Media Type: ").append(codec.getMediaType()).append(" | "); - sb.append("Name: ").append(codec.getName()).append(" | "); - sb.append("Clock Rate: ").append(codec.getClockRate()).append(" Hz"); - - if (codec.getMediaType() == MediaType.AUDIO) { - int channels = codec.getChannels(); - sb.append(" | Channels: ").append(channels) - .append(channels == 1 ? " (mono)" : channels == 2 ? " (stereo)" : ""); - } - - // Add SDP format parameters if available. - Map sdpFmtp = codec.getSDPFmtp(); - if (sdpFmtp != null && !sdpFmtp.isEmpty()) { - sb.append(" | SDP Params: {"); - boolean first = true; - for (Map.Entry entry : sdpFmtp.entrySet()) { - if (!first) { - sb.append(", "); - } - sb.append(entry.getKey()).append("=").append(entry.getValue()); - first = false; - } - sb.append("}"); - } - - System.out.println(sb); - } - } -} \ No newline at end of file diff --git a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/DesktopVideoExample.java b/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/DesktopVideoExample.java deleted file mode 100644 index ee95938..0000000 --- a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/DesktopVideoExample.java +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright 2025 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.examples; - -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - -import dev.onvoid.webrtc.PeerConnectionFactory; -import dev.onvoid.webrtc.PeerConnectionObserver; -import dev.onvoid.webrtc.RTCConfiguration; -import dev.onvoid.webrtc.RTCDataChannel; -import dev.onvoid.webrtc.RTCIceCandidate; -import dev.onvoid.webrtc.RTCIceConnectionState; -import dev.onvoid.webrtc.RTCIceGatheringState; -import dev.onvoid.webrtc.RTCIceServer; -import dev.onvoid.webrtc.RTCPeerConnection; -import dev.onvoid.webrtc.RTCPeerConnectionState; -import dev.onvoid.webrtc.RTCRtpReceiver; -import dev.onvoid.webrtc.RTCRtpTransceiver; -import dev.onvoid.webrtc.RTCSignalingState; -import dev.onvoid.webrtc.media.MediaStream; -import dev.onvoid.webrtc.media.MediaStreamTrack; -import dev.onvoid.webrtc.media.video.VideoDesktopSource; -import dev.onvoid.webrtc.media.video.VideoTrack; -import dev.onvoid.webrtc.media.video.desktop.DesktopSource; -import dev.onvoid.webrtc.media.video.desktop.ScreenCapturer; -import dev.onvoid.webrtc.media.video.desktop.WindowCapturer; - -/** - * Example demonstrating how to set up a peer connection with a desktop video source. - *

- * This example shows how to: - *

    - *
  • Create a PeerConnectionFactory
  • - *
  • Get available desktop sources (screens and windows)
  • - *
  • Create a VideoDesktopSource for capturing screen or window content
  • - *
  • Configure the VideoDesktopSource properties
  • - *
  • Create a video track with the desktop source
  • - *
  • Set up a peer connection
  • - *
- *

- * Note: This example focuses only on setting up the local peer connection with - * a desktop video source for bidirectional media transfer. In a real application, - * you would need to establish a connection with a remote peer through a signaling - * channel (e.g., WebSocket). - * - * @author Alex Andres - */ -public class DesktopVideoExample { - - public static void main(String[] args) { - // Create a PeerConnectionFactory, which is the main entry point for WebRTC. - PeerConnectionFactory factory = new PeerConnectionFactory(); - - try { - LocalPeer localPeer = new LocalPeer(factory); - - // Keep the application running to observe state changes. - System.out.println("Press Enter to exit..."); - System.in.read(); - - // Clean up. - localPeer.dispose(); - } - catch (Exception e) { - Logger.getLogger(DesktopVideoExample.class.getName()) - .log(Level.SEVERE, "Error in DesktopVideoExample", e); - } - finally { - // Dispose the factory when done. - factory.dispose(); - } - } - - /** - * Represents a peer connection with audio and desktop video tracks. - */ - private static class LocalPeer implements PeerConnectionObserver { - - private final RTCPeerConnection peerConnection; - private final VideoDesktopSource videoSource; - - - public LocalPeer(PeerConnectionFactory factory) { - // Create a basic configuration for the peer connection. - RTCConfiguration config = new RTCConfiguration(); - - // Add a STUN server to help with NAT traversal. - RTCIceServer iceServer = new RTCIceServer(); - iceServer.urls.add("stun:stun.l.google.com:19302"); - config.iceServers.add(iceServer); - - // Create the peer connection. - peerConnection = factory.createPeerConnection(config, this); - - // Get available desktop sources. - System.out.println("Getting available desktop sources..."); - - // Get available screens. - ScreenCapturer screenCapturer = new ScreenCapturer(); - List screens = screenCapturer.getDesktopSources(); - System.out.println("\nAvailable screens:"); - for (DesktopSource screen : screens) { - System.out.printf(" Screen: %s (ID: %d)%n", screen.title, screen.id); - } - - // Get available windows. - WindowCapturer windowCapturer = new WindowCapturer(); - List windows = windowCapturer.getDesktopSources(); - System.out.println("\nAvailable windows:"); - for (DesktopSource window : windows) { - System.out.printf(" Window: %s (ID: %d)%n", window.title, window.id); - } - - // Clean up the capturers as we only needed them to get the sources. - screenCapturer.dispose(); - windowCapturer.dispose(); - - // Create a desktop video source. - videoSource = new VideoDesktopSource(); - - // Configure the desktop video source. - // Set frame rate (e.g., 30 fps). - videoSource.setFrameRate(30); - - // Set maximum frame size (e.g., 1920x1080). - videoSource.setMaxFrameSize(1920, 1080); - - // Select a source to capture. - // For this example; we'll use the first available screen if there is one. - if (!screens.isEmpty()) { - DesktopSource selectedScreen = screens.get(0); - System.out.printf("%nSelected screen for capture: %s (ID: %d)%n", - selectedScreen.title, selectedScreen.id); - videoSource.setSourceId(selectedScreen.id, false); - } - // Otherwise, use the first available window if there is one. - else if (!windows.isEmpty()) { - DesktopSource selectedWindow = windows.get(0); - System.out.printf("%nSelected window for capture: %s (ID: %d)%n", - selectedWindow.title, selectedWindow.id); - videoSource.setSourceId(selectedWindow.id, true); - } - // If no sources are available, fall back to a default (primary screen). - else { - System.out.println("\nNo desktop sources found. Using default (primary screen)."); - videoSource.setSourceId(0, false); - } - - // Start capturing. - videoSource.start(); - - // Create a video track with the desktop source. - VideoTrack videoTrack = factory.createVideoTrack("video0", videoSource); - - // Add the tracks to the peer connection. - List streamIds = new ArrayList<>(); - streamIds.add("stream1"); - peerConnection.addTrack(videoTrack, streamIds); - - System.out.println("LocalPeer: Created with a desktop video track"); - } - - /** - * Closes the peer connection and releases resources. - */ - public void dispose() { - if (videoSource != null) { - // Stop capturing before disposing. - videoSource.stop(); - videoSource.dispose(); - } - if (peerConnection != null) { - peerConnection.close(); - } - } - - // PeerConnectionObserver implementation. - - @Override - public void onIceCandidate(RTCIceCandidate candidate) { - System.out.println("LocalPeer: New ICE candidate: " + candidate.sdp); - // In a real application, you would send this candidate to the remote peer - // through your signaling channel. - } - - @Override - public void onConnectionChange(RTCPeerConnectionState state) { - System.out.println("LocalPeer: Connection state changed to: " + state); - } - - @Override - public void onIceConnectionChange(RTCIceConnectionState state) { - System.out.println("LocalPeer: ICE connection state changed to: " + state); - } - - @Override - public void onIceGatheringChange(RTCIceGatheringState state) { - System.out.println("LocalPeer: ICE gathering state changed to: " + state); - } - - @Override - public void onSignalingChange(RTCSignalingState state) { - System.out.println("LocalPeer: Signaling state changed to: " + state); - } - - @Override - public void onDataChannel(RTCDataChannel dataChannel) { - System.out.println("LocalPeer: Data channel created: " + dataChannel.getLabel()); - } - - @Override - public void onRenegotiationNeeded() { - System.out.println("LocalPeer: Renegotiation needed"); - // In a real application, you would create an offer and set it as the local description. - } - - @Override - public void onAddTrack(RTCRtpReceiver receiver, MediaStream[] mediaStreams) { - System.out.println("LocalPeer: Track added: " + receiver.getTrack().getKind()); - } - - @Override - public void onRemoveTrack(RTCRtpReceiver receiver) { - System.out.println("LocalPeer: Track removed: " + receiver.getTrack().getKind()); - } - - @Override - public void onTrack(RTCRtpTransceiver transceiver) { - MediaStreamTrack track = transceiver.getReceiver().getTrack(); - - System.out.println("LocalPeer: Transceiver track added: " + track.getKind()); - } - } -} \ No newline at end of file diff --git a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/PeerConnectionExample.java b/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/PeerConnectionExample.java deleted file mode 100644 index 2c670cd..0000000 --- a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/PeerConnectionExample.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright 2025 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.examples; - -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - -import dev.onvoid.webrtc.PeerConnectionFactory; -import dev.onvoid.webrtc.PeerConnectionObserver; -import dev.onvoid.webrtc.RTCConfiguration; -import dev.onvoid.webrtc.RTCDataChannel; -import dev.onvoid.webrtc.RTCIceCandidate; -import dev.onvoid.webrtc.RTCIceConnectionState; -import dev.onvoid.webrtc.RTCIceGatheringState; -import dev.onvoid.webrtc.RTCIceServer; -import dev.onvoid.webrtc.RTCPeerConnection; -import dev.onvoid.webrtc.RTCPeerConnectionState; -import dev.onvoid.webrtc.RTCRtpReceiver; -import dev.onvoid.webrtc.RTCRtpTransceiver; -import dev.onvoid.webrtc.RTCSignalingState; -import dev.onvoid.webrtc.media.MediaStream; -import dev.onvoid.webrtc.media.MediaStreamTrack; -import dev.onvoid.webrtc.media.audio.AudioOptions; -import dev.onvoid.webrtc.media.audio.AudioTrack; -import dev.onvoid.webrtc.media.audio.AudioTrackSink; -import dev.onvoid.webrtc.media.audio.AudioTrackSource; -import dev.onvoid.webrtc.media.video.VideoDeviceSource; -import dev.onvoid.webrtc.media.video.VideoFrame; -import dev.onvoid.webrtc.media.video.VideoTrack; -import dev.onvoid.webrtc.media.video.VideoTrackSink; - -/** - * Example demonstrating how to set up a peer connection with audio and video tracks - * to be able to send and receive media. - *

- * This example shows how to: - *

    - *
  • Create a PeerConnectionFactory
  • - *
  • Create audio and video tracks
  • - *
  • Set up a peer connection
  • - *
  • Add tracks to the peer connection for sending media
  • - *
  • Implement callbacks to receive incoming audio and video frames
  • - *
- *

- * Note: This example focuses only on setting up the local peer connection with - * audio and video tracks for bidirectional media transfer. In a real application, - * you would need to establish a connection with a remote peer through a signaling - * channel (e.g., WebSocket). - * - * @author Alex Andres - */ -public class PeerConnectionExample { - - public static void main(String[] args) { - // Create a PeerConnectionFactory, which is the main entry point for WebRTC. - PeerConnectionFactory factory = new PeerConnectionFactory(); - - try { - LocalPeer localPeer = new LocalPeer(factory); - - // Keep the application running to observe state changes. - System.out.println("Press Enter to exit..."); - System.in.read(); - - // Clean up. - localPeer.dispose(); - } - catch (Exception e) { - Logger.getLogger(PeerConnectionExample.class.getName()) - .log(Level.SEVERE, "Error in PeerConnectionExample", e); - } - finally { - // Dispose the factory when done - factory.dispose(); - } - } - - /** - * Represents a peer connection with audio and video tracks. - */ - private static class LocalPeer implements PeerConnectionObserver { - - private final RTCPeerConnection peerConnection; - private final AudioTrack audioTrack; - private final VideoTrack videoTrack; - private final AudioFrameLogger audioFrameLogger = new AudioFrameLogger(); - private final VideoFrameLogger videoFrameLogger = new VideoFrameLogger(); - - - public LocalPeer(PeerConnectionFactory factory) { - // Create a basic configuration for the peer connection. - RTCConfiguration config = new RTCConfiguration(); - - // Add a STUN server to help with NAT traversal. - RTCIceServer iceServer = new RTCIceServer(); - iceServer.urls.add("stun:stun.l.google.com:19302"); - config.iceServers.add(iceServer); - - // Create the peer connection. - peerConnection = factory.createPeerConnection(config, this); - - // Create an audio source with options. - AudioOptions audioOptions = new AudioOptions(); - audioOptions.echoCancellation = true; - audioOptions.autoGainControl = true; - audioOptions.noiseSuppression = true; - - AudioTrackSource audioSource = factory.createAudioSource(audioOptions); - audioTrack = factory.createAudioTrack("audio0", audioSource); - - VideoDeviceSource videoSource = new VideoDeviceSource(); - videoTrack = factory.createVideoTrack("video0", videoSource); - - // Add the tracks to the peer connection. - List streamIds = new ArrayList<>(); - streamIds.add("stream1"); - peerConnection.addTrack(audioTrack, streamIds); - peerConnection.addTrack(videoTrack, streamIds); - - System.out.println("LocalPeer: Created with audio and video tracks"); - } - - /** - * Closes the peer connection and releases resources. - */ - public void dispose() { - if (audioTrack != null) { - audioTrack.removeSink(audioFrameLogger); - } - if (videoTrack != null) { - videoTrack.removeSink(videoFrameLogger); - } - if (peerConnection != null) { - peerConnection.close(); - } - } - - // PeerConnectionObserver implementation. - - @Override - public void onIceCandidate(RTCIceCandidate candidate) { - System.out.println("LocalPeer: New ICE candidate: " + candidate.sdp); - // In a real application, you would send this candidate to the remote peer - // through your signaling channel. - } - - @Override - public void onConnectionChange(RTCPeerConnectionState state) { - System.out.println("LocalPeer: Connection state changed to: " + state); - } - - @Override - public void onIceConnectionChange(RTCIceConnectionState state) { - System.out.println("LocalPeer: ICE connection state changed to: " + state); - } - - @Override - public void onIceGatheringChange(RTCIceGatheringState state) { - System.out.println("LocalPeer: ICE gathering state changed to: " + state); - } - - @Override - public void onSignalingChange(RTCSignalingState state) { - System.out.println("LocalPeer: Signaling state changed to: " + state); - } - - @Override - public void onDataChannel(RTCDataChannel dataChannel) { - System.out.println("LocalPeer: Data channel created: " + dataChannel.getLabel()); - } - - @Override - public void onRenegotiationNeeded() { - System.out.println("LocalPeer: Renegotiation needed"); - // In a real application, you would create an offer and set it as the local description. - } - - @Override - public void onAddTrack(RTCRtpReceiver receiver, MediaStream[] mediaStreams) { - System.out.println("LocalPeer: Track added: " + receiver.getTrack().getKind()); - } - - @Override - public void onRemoveTrack(RTCRtpReceiver receiver) { - System.out.println("LocalPeer: Track removed: " + receiver.getTrack().getKind()); - } - - @Override - public void onTrack(RTCRtpTransceiver transceiver) { - MediaStreamTrack track = transceiver.getReceiver().getTrack(); - String kind = track.getKind(); - - if (kind.equals(MediaStreamTrack.AUDIO_TRACK_KIND)) { - AudioTrack audioTrack = (AudioTrack) track; - audioTrack.addSink(audioFrameLogger); - } - if (kind.equals(MediaStreamTrack.VIDEO_TRACK_KIND)) { - VideoTrack videoTrack = (VideoTrack) track; - videoTrack.addSink(videoFrameLogger); - } - - System.out.println("LocalPeer: Transceiver track added: " + kind); - } - } - - - - /** - * A simple implementation of VideoTrackSink that logs information about received frames. - */ - private static class VideoFrameLogger implements VideoTrackSink { - - private static final long LOG_INTERVAL_MS = 1000; // Log every second - private int frameCount = 0; - private long lastLogTime = System.currentTimeMillis(); - - - @Override - public void onVideoFrame(VideoFrame frame) { - frameCount++; - - long now = System.currentTimeMillis(); - if (now - lastLogTime >= LOG_INTERVAL_MS) { - System.out.printf("Received %d video frames in the last %.1f seconds%n", - frameCount, (now - lastLogTime) / 1000.0); - System.out.printf("Last frame: %dx%d, rotation: %d, timestamp: %dms%n", - frame.buffer.getWidth(), frame.buffer.getHeight(), frame.rotation, - frame.timestampNs / 1000000); - - frameCount = 0; - lastLogTime = now; - } - - // Release the native resources associated with this frame to prevent memory leaks. - frame.release(); - } - } - - - - /** - * A simple implementation of AudioTrackSink that logs information about received audio data. - */ - private static class AudioFrameLogger implements AudioTrackSink { - - private static final long LOG_INTERVAL_MS = 1000; // Log every second - private int frameCount = 0; - private long lastLogTime = System.currentTimeMillis(); - - - @Override - public void onData(byte[] data, int bitsPerSample, int sampleRate, int channels, int frames) { - frameCount++; - - long now = System.currentTimeMillis(); - if (now - lastLogTime >= LOG_INTERVAL_MS) { - System.out.printf("Received %d audio frames in the last %.1f seconds%n", - frameCount, (now - lastLogTime) / 1000.0); - System.out.printf("Last audio data: %d bytes, %d bits/sample, %d Hz, %d channels, %d frames%n", - data.length, bitsPerSample, sampleRate, channels, frames); - - frameCount = 0; - lastLogTime = now; - } - } - } -} \ No newline at end of file diff --git a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/WhepExample.java b/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/WhepExample.java deleted file mode 100644 index 46a49c9..0000000 --- a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/WhepExample.java +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright 2025 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.examples; - -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.time.Duration; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.logging.Level; -import java.util.logging.Logger; - -import dev.onvoid.webrtc.*; -import dev.onvoid.webrtc.media.MediaStream; -import dev.onvoid.webrtc.media.MediaStreamTrack; -import dev.onvoid.webrtc.media.video.VideoDeviceSource; -import dev.onvoid.webrtc.media.video.VideoTrack; - -/** - * Example implementation of WebRTC HTTP Egress Protocol (WHEP) client. - *

- * This class demonstrates: - *

    - *
  • Setting up a WebRTC peer connection
  • - *
  • Creating and sending an SDP offer to a WHEP endpoint
  • - *
  • Receiving and processing an SDP answer
  • - *
  • Establishing media streaming over WebRTC
  • - *
- *

- * The example creates a receive-only peer connection that can accept - * incoming video streams from a WHEP-compatible server. - * - * @see WHEP Specification - * - * @author Alex Andres - */ -public class WhepExample { - - private static final String WHEP_ENDPOINT_URL = "http://localhost:8889/mystream/whep"; - - /** Factory for creating peer connections and media objects. */ - private PeerConnectionFactory factory; - - /** The WebRTC peer connection that handles media communication. */ - private RTCPeerConnection peerConnection; - - /** The local SDP offer to be sent to the remote endpoint. */ - private RTCSessionDescription localOffer; - - // Synchronization objects for async operations. - private final CountDownLatch offerCreatedLatch = new CountDownLatch(1); - private final CountDownLatch localDescriptionSetLatch = new CountDownLatch(1); - private final CountDownLatch remoteDescriptionSetLatch = new CountDownLatch(1); - - - public static void main(String[] args) { - WhepExample example = new WhepExample(); - - try { - example.run(); - } - catch (Exception e) { - Logger.getLogger("WHEPExample").log(Level.SEVERE, "Error running WHEP example", e); - } - finally { - example.cleanup(); - } - } - - public void run() throws Exception { - System.out.println("Starting WebRTC Peer Connection Example"); - - initializePeerConnectionFactory(); - createPeerConnection(); - createOffer(); - - // Wait for the offer to be created. - if (!offerCreatedLatch.await(5, TimeUnit.SECONDS)) { - throw new IllegalStateException("Timeout waiting for offer creation."); - } - - // Set the local description (the offer). - setLocalDescription(localOffer); - - // Wait for the local description to be set. - if (!localDescriptionSetLatch.await(5, TimeUnit.SECONDS)) { - throw new IllegalStateException("Timeout waiting for local description to be set."); - } - - System.out.println("Local offer created and set."); - //System.out.println("SDP Offer: " + localOffer.sdp); - System.out.println("Sending local offer to the remote endpoint."); - - String answerSdp = sendOfferEndpoint(localOffer.sdp); - - //System.out.println("SDP Answer: " + answerSdp); - - // Set the remote description (the answer). - setRemoteDescription(new RTCSessionDescription(RTCSdpType.ANSWER, answerSdp)); - - // Wait for the remote description to be set. - if (!remoteDescriptionSetLatch.await(5, TimeUnit.SECONDS)) { - throw new IllegalStateException("Timeout waiting for remote description to be set."); - } - - System.out.println("Remote answer set. Peer connection established!"); - System.out.println("Media should now be exchanged between peers."); - - // Wait a bit to see connection state changes. - Thread.sleep(10000); - - System.out.println("WebRTC Peer Connection Example completed."); - } - - private void initializePeerConnectionFactory() { - System.out.println("Initializing PeerConnectionFactory."); - factory = new PeerConnectionFactory(); - } - - private void createPeerConnection() { - System.out.println("Creating peer connection."); - - // Create ICE servers configuration. - RTCConfiguration config = new RTCConfiguration(); - - // Add Google's public STUN server. - RTCIceServer iceServer = new RTCIceServer(); - iceServer.urls.add("stun:stun.l.google.com:19302"); - config.iceServers.add(iceServer); - - // Create the peer connection with our observer. - peerConnection = factory.createPeerConnection(config, new PeerConnectionObserverImpl()); - - // Create a video track from a video device source (e.g., webcam). - // Since we are only receiving video in this example, the source will be a dummy video source. - VideoDeviceSource videoSource = new VideoDeviceSource(); - VideoTrack videoTrack = factory.createVideoTrack("videoTrack", videoSource); - videoTrack.addSink(videoFrame -> System.out.println("Received video frame: " + videoFrame)); - - // Only interested in receiving video, so we set up a transceiver for that. - RTCRtpTransceiverInit transceiverInit = new RTCRtpTransceiverInit(); - transceiverInit.direction = RTCRtpTransceiverDirection.RECV_ONLY; - - // Add the transceiver to the peer connection with the video track. - RTCRtpTransceiver transceiver = peerConnection.addTransceiver(videoTrack, transceiverInit); - - // Set up a sink to handle incoming video frames. - MediaStreamTrack track = transceiver.getReceiver().getTrack(); - if (track instanceof VideoTrack vTrack) { - vTrack.addSink(videoFrame -> { - System.out.println("Received video frame: " + videoFrame); - - // IMPORTANT: Always release the frame when done to prevent memory leaks - videoFrame.release(); - }); - } - } - - private void createOffer() { - System.out.println("Creating offer."); - - // Create offer options (use default options). - RTCOfferOptions options = new RTCOfferOptions(); - - // Create the offer. - peerConnection.createOffer(options, new CreateSessionDescriptionObserver() { - @Override - public void onSuccess(RTCSessionDescription description) { - System.out.println("Offer created successfully."); - localOffer = description; - offerCreatedLatch.countDown(); - } - - @Override - public void onFailure(String error) { - System.err.println("Failed to create offer: " + error); - offerCreatedLatch.countDown(); - } - }); - } - - private void setLocalDescription(RTCSessionDescription description) { - System.out.println("Setting local description."); - - peerConnection.setLocalDescription(description, new SetSessionDescriptionObserver() { - @Override - public void onSuccess() { - System.out.println("Local description set successfully."); - localDescriptionSetLatch.countDown(); - } - - @Override - public void onFailure(String error) { - System.err.println("Failed to set local description: " + error); - localDescriptionSetLatch.countDown(); - } - }); - } - - private String sendOfferEndpoint(String sdpOffer) throws Exception { - HttpClient client = HttpClient.newBuilder() - .connectTimeout(Duration.ofSeconds(10)) - .build(); - - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(WHEP_ENDPOINT_URL)) - .header("Content-Type", "application/sdp") - .POST(HttpRequest.BodyPublishers.ofString(sdpOffer)) - .timeout(Duration.ofSeconds(30)) - .build(); - - HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); - - if (response.statusCode() == 200 || response.statusCode() == 201) { - System.out.println("WHEP request successful"); - return response.body(); - } - else { - throw new RuntimeException("WHEP request failed with status: " + response.statusCode()); - } - } - - private void setRemoteDescription(RTCSessionDescription description) { - System.out.println("Setting remote description."); - - peerConnection.setRemoteDescription(description, new SetSessionDescriptionObserver() { - @Override - public void onSuccess() { - System.out.println("Remote description set successfully."); - remoteDescriptionSetLatch.countDown(); - } - - @Override - public void onFailure(String error) { - System.err.println("Failed to set remote description: " + error); - remoteDescriptionSetLatch.countDown(); - } - }); - } - - private void cleanup() { - System.out.println("Cleaning up resources."); - - if (peerConnection != null) { - peerConnection.close(); - peerConnection = null; - } - - if (factory != null) { - factory.dispose(); - factory = null; - } - } - - - - /** - * Implementation of PeerConnectionObserver to handle events from the peer connection. - */ - private static class PeerConnectionObserverImpl implements PeerConnectionObserver { - - @Override - public void onIceCandidate(RTCIceCandidate candidate) { - System.out.println("ICE candidate: " + candidate.sdp); - // In a real application, we would send this candidate to the remote peer - } - - @Override - public void onConnectionChange(RTCPeerConnectionState state) { - System.out.println("Connection state changed: " + state); - } - - @Override - public void onIceConnectionChange(RTCIceConnectionState state) { - System.out.println("ICE connection state changed: " + state); - } - - @Override - public void onIceGatheringChange(RTCIceGatheringState state) { - System.out.println("ICE gathering state changed: " + state); - } - - @Override - public void onSignalingChange(RTCSignalingState state) { - System.out.println("Signaling state changed: " + state); - } - - @Override - public void onDataChannel(RTCDataChannel dataChannel) { - System.out.println("Data channel created: " + dataChannel.getLabel()); - } - - @Override - public void onRenegotiationNeeded() { - System.out.println("Renegotiation needed."); - } - - @Override - public void onAddTrack(RTCRtpReceiver receiver, MediaStream[] mediaStreams) { - System.out.println("Track added."); - } - } -} \ No newline at end of file diff --git a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/util/MediaFrameLogger.java b/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/util/MediaFrameLogger.java deleted file mode 100644 index ae1f748..0000000 --- a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/util/MediaFrameLogger.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2025 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.examples.util; - -import dev.onvoid.webrtc.media.audio.AudioTrackSink; -import dev.onvoid.webrtc.media.video.VideoFrame; -import dev.onvoid.webrtc.media.video.VideoTrackSink; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Utility class for logging audio and video frame information. - * - * @author Alex Andres - */ -public class MediaFrameLogger { - - private static final Logger LOG = LoggerFactory.getLogger(MediaFrameLogger.class); - - - /** - * Creates a new audio track sink that logs information about received audio data. - * - * @return An AudioTrackSink that logs audio frame information. - */ - public static AudioTrackSink createAudioLogger() { - return new AudioFrameLogger(); - } - - /** - * Creates a new video track sink that logs information about received video frames. - * - * @return A VideoTrackSink that logs video frame information. - */ - public static VideoTrackSink createVideoLogger() { - return new VideoFrameLogger(); - } - - - - /** - * A simple implementation of AudioTrackSink that logs information about received audio data. - */ - private static class AudioFrameLogger implements AudioTrackSink { - - private static final long LOG_INTERVAL_MS = 1000; // Log every second - private int frameCount = 0; - private long lastLogTime = System.currentTimeMillis(); - - @Override - public void onData(byte[] data, int bitsPerSample, int sampleRate, int channels, int frames) { - frameCount++; - - long now = System.currentTimeMillis(); - if (now - lastLogTime >= LOG_INTERVAL_MS) { - LOG.info(String.format("Received %d audio frames in the last %.1f seconds", - frameCount, (now - lastLogTime) / 1000.0)); - LOG.info(String.format("Last audio data: %d bytes, %d bits/sample, %d Hz, %d channels, %d frames", - data.length, bitsPerSample, sampleRate, channels, frames)); - - frameCount = 0; - lastLogTime = now; - } - } - } - - - - /** - * A simple implementation of VideoTrackSink that logs information about received frames. - */ - private static class VideoFrameLogger implements VideoTrackSink { - - private static final long LOG_INTERVAL_MS = 1000; // Log every second - private int frameCount = 0; - private long lastLogTime = System.currentTimeMillis(); - - @Override - public void onVideoFrame(VideoFrame frame) { - frameCount++; - - long now = System.currentTimeMillis(); - if (now - lastLogTime >= LOG_INTERVAL_MS) { - LOG.info(String.format("Received %d video frames in the last %.1f seconds", - frameCount, (now - lastLogTime) / 1000.0)); - LOG.info(String.format("Last frame: %dx%d, rotation: %d, timestamp: %dms", - frame.buffer.getWidth(), frame.buffer.getHeight(), frame.rotation, - frame.timestampNs / 1000000)); - - frameCount = 0; - lastLogTime = now; - } - - // Release the native resources associated with this frame to prevent memory leaks. - frame.release(); - } - } -} \ No newline at end of file diff --git a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/WebClientExample.java b/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/WebClientExample.java deleted file mode 100644 index 80efc98..0000000 --- a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/WebClientExample.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright 2025 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.examples.web; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.util.logging.LogManager; - -import dev.onvoid.webrtc.examples.web.model.LeaveMessage; -import dev.onvoid.webrtc.media.MediaStreamTrack; - -import dev.onvoid.webrtc.examples.web.client.SignalingManager; -import dev.onvoid.webrtc.examples.web.connection.PeerConnectionManager; -import dev.onvoid.webrtc.examples.web.media.MediaManager; -import dev.onvoid.webrtc.examples.web.model.JoinMessage; -import dev.onvoid.webrtc.examples.util.MediaFrameLogger; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Example demonstrating how to combine WebSocket signaling with WebRTC peer connections. - *

- * This example shows how to: - *

    - *
  • Connect to a signaling server using WebSockets
  • - *
  • Set up media tracks
  • - *
  • Establish a WebRTC peer connection with audio and video
  • - *
- * - * @author Alex Andres - */ -public class WebClientExample { - - static { - setupLogging(); - } - - private static final Logger LOG = LoggerFactory.getLogger(WebClientExample.class); - - /** Manages communication with the signaling server. */ - private final SignalingManager signaling; - - /** Handles WebRTC peer connection setup and management. */ - private final PeerConnectionManager peerConnectionManager; - - /** Manages audio and video tracks and devices. */ - private final MediaManager mediaManager; - - - /** - * Creates a new WebClientExample that combines WebSocket signaling with WebRTC. - * - * @param signalingUri The URI of the signaling server. - * @param subprotocol The WebSocket subprotocol to use. - */ - public WebClientExample(URI signalingUri, String subprotocol) { - signaling = new SignalingManager(signalingUri, subprotocol); - signaling.setUserId("java-client"); - - peerConnectionManager = new PeerConnectionManager(); - - mediaManager = new MediaManager(); - mediaManager.createTracks(peerConnectionManager, true, true); - - setupCallbacks(); - - LOG.info("WebClientExample created with audio and video tracks"); - } - - /** - * Sets up callbacks between components. - */ - private void setupCallbacks() { - // Set up signaling callbacks. - signaling.setOnOfferReceived(peerConnectionManager::handleOffer); - signaling.setOnAnswerReceived(peerConnectionManager::handleAnswer); - signaling.setOnCandidateReceived(peerConnectionManager::handleCandidate); - signaling.setOnJoinReceived(this::handleJoin); - signaling.setOnLeaveReceived(this::handleLeave); - - // Set up peer connection callbacks. - peerConnectionManager.setOnLocalDescriptionCreated(signaling::sendSessionDescription); - peerConnectionManager.setOnIceCandidateGenerated(signaling::sendIceCandidate); - peerConnectionManager.setOnTrackReceived(this::handleTrackReceived); - } - - /** - * Handles a received media track. - * - * @param track The received media track. - */ - private void handleTrackReceived(MediaStreamTrack track) { - String kind = track.getKind(); - LOG.info("Received track: {}", kind); - - if (kind.equals(MediaStreamTrack.AUDIO_TRACK_KIND)) { - mediaManager.addAudioSink(MediaFrameLogger.createAudioLogger()); - } - else if (kind.equals(MediaStreamTrack.VIDEO_TRACK_KIND)) { - mediaManager.addVideoSink(MediaFrameLogger.createVideoLogger()); - } - } - - /** - * Connects to the signaling server. - * - * @return true if the connection was successful, false otherwise. - */ - public boolean connect() { - return signaling.connect(); - } - - /** - * Disconnects from the signaling server and closes the peer connection. - */ - public void disconnect() { - signaling.disconnect(); - - if (mediaManager != null) { - mediaManager.dispose(); - } - if (peerConnectionManager != null) { - peerConnectionManager.close(); - } - - LOG.info("Disconnected from signaling server and closed peer connection"); - } - - /** - * Joins a room on the signaling server. - *

- * This method sends a join request to the signaling server for the specified room. - * - * @param roomName the name of the room to join on the signaling server - */ - public void joinRoom(String roomName) { - if (!signaling.isConnected()) { - LOG.warn("Cannot join room: not connected to signaling server"); - return; - } - - signaling.sendJoin(roomName); - } - - /** - * Initiates a call by creating and sending an offer. - */ - public void call() { - if (!signaling.isConnected()) { - LOG.warn("Cannot initiate call: not connected to signaling server"); - return; - } - - peerConnectionManager.setInitiator(true); - peerConnectionManager.createOffer(); - } - - /** - * Handles an incoming join message from the remote peer. - * - * @param message The join message. - */ - private void handleJoin(JoinMessage message) { - LOG.info("Received join message from peer: {}", message.getFrom()); - - // Remote peer wants to join a room, we need to create an offer if we're not the initiator. - if (!peerConnectionManager.isInitiator()) { - peerConnectionManager.createOffer(); - } - } - - /** - * Handles an incoming leave message from the remote peer. - * - * @param message The leave message. - */ - private void handleLeave(LeaveMessage message) { - LOG.info("Peer {} has left the room", message.getFrom()); - - // Handle peer leaving logic, such as closing tracks or updating UI. - } - - /** - * Entry point to demonstrate the WebClientExample. - */ - public static void main(String[] args) { - try { - WebClientExample client = new WebClientExample( - URI.create("wss://localhost:8443/ws"), - "ws-signaling"); - - if (client.connect()) { - LOG.info("Connected to signaling server"); - - // Join a room. - client.joinRoom("default-room"); - - // Initiate the call. - client.call(); - - // Keep the application running to observe state changes. - System.out.println("Press Enter to exit..."); - System.in.read(); - } - else { - LOG.error("Failed to connect to signaling server"); - } - - // Clean up. - client.disconnect(); - } - catch (Exception e) { - LOG.error("Error in WebClientExample", e); - } - } - - /** - * Sets up logging for the application. - */ - public static void setupLogging() { - try { - InputStream configFile = WebClientExample.class.getResourceAsStream("/resources/logging.properties"); - LogManager.getLogManager().readConfiguration(configFile); - } - catch (IOException e) { - System.err.println("Could not load configuration file:"); - System.err.println(e.getMessage()); - } - } -} \ No newline at end of file diff --git a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/connection/PeerConnectionManager.java b/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/connection/PeerConnectionManager.java index fbece89..8880298 100644 --- a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/connection/PeerConnectionManager.java +++ b/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/connection/PeerConnectionManager.java @@ -32,23 +32,12 @@ import dev.onvoid.webrtc.RTCOfferOptions; import dev.onvoid.webrtc.RTCPeerConnection; import dev.onvoid.webrtc.RTCPeerConnectionState; -import dev.onvoid.webrtc.RTCRtpReceiver; -import dev.onvoid.webrtc.RTCRtpTransceiver; import dev.onvoid.webrtc.RTCSdpType; import dev.onvoid.webrtc.RTCSessionDescription; import dev.onvoid.webrtc.RTCSignalingState; import dev.onvoid.webrtc.SetSessionDescriptionObserver; import dev.onvoid.webrtc.examples.web.model.IceCandidateMessage; import dev.onvoid.webrtc.examples.web.model.SessionDescriptionMessage; -import dev.onvoid.webrtc.media.MediaStream; -import dev.onvoid.webrtc.media.MediaStreamTrack; - -import dev.onvoid.webrtc.media.audio.AudioOptions; -import dev.onvoid.webrtc.media.audio.AudioTrack; -import dev.onvoid.webrtc.media.audio.AudioTrackSource; -import dev.onvoid.webrtc.media.audio.CustomAudioSource; -import dev.onvoid.webrtc.media.video.VideoTrack; -import dev.onvoid.webrtc.media.video.VideoTrackSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -69,7 +58,6 @@ public class PeerConnectionManager implements PeerConnectionSignalingHandler { private Consumer onLocalDescriptionCreated; private Consumer onIceCandidateGenerated; - private Consumer onTrackReceived; private boolean isInitiator = false; @@ -92,56 +80,6 @@ public PeerConnectionManager() { LOG.info("PeerConnectionManager created"); } - /** - * Adds a media track to the peer connection. - * - * @param track The media track to add. - * @param streamIds The stream IDs to associate with the track. - */ - public void addTrack(MediaStreamTrack track, List streamIds) { - peerConnection.addTrack(track, streamIds); - - LOG.info("Added track: {}", track.getKind()); - } - - /** - * Creates an audio track with the specified options and label. - * - * @param options Configuration options for the audio track source. - * @param label A unique identifier for the audio track. - * - * @return A new AudioTrack instance configured with the provided options. - */ - public AudioTrack createAudioTrack(AudioOptions options, String label) { - AudioTrackSource audioSource = factory.createAudioSource(options); - - return factory.createAudioTrack(label, audioSource); - } - - /** - * Creates an audio track with a custom audio source that can push audio frames. - * - * @param source The custom audio source providing the audio frames. - * @param label A unique identifier for the audio track. - * - * @return A new AudioTrack instance connected to the provided custom source. - */ - public AudioTrack createAudioTrack(CustomAudioSource source, String label) { - return factory.createAudioTrack(label, source); - } - - /** - * Creates a video track with the specified source and label. - * - * @param source The video track source providing the video frames. - * @param label A unique identifier for the video track. - * - * @return A new VideoTrack instance connected to the provided source. - */ - public VideoTrack createVideoTrack(VideoTrackSource source, String label) { - return factory.createVideoTrack(label, source); - } - /** * Closes the peer connection. */ @@ -268,15 +206,6 @@ public void setOnLocalDescriptionCreated(Consumer callbac public void setOnIceCandidateGenerated(Consumer callback) { this.onIceCandidateGenerated = callback; } - - /** - * Sets a callback to be invoked when a media track is received. - * - * @param callback The callback to invoke. - */ - public void setOnTrackReceived(Consumer callback) { - this.onTrackReceived = callback; - } /** * Sets whether this peer is the initiator of the connection. @@ -403,27 +332,5 @@ public void onRenegotiationNeeded() { LOG.info("Renegotiation needed"); createOffer(); } - - @Override - public void onAddTrack(RTCRtpReceiver receiver, MediaStream[] mediaStreams) { - LOG.info("Track added: {}", receiver.getTrack().getKind()); - } - - @Override - public void onRemoveTrack(RTCRtpReceiver receiver) { - LOG.info("Track removed: {}", receiver.getTrack().getKind()); - } - - @Override - public void onTrack(RTCRtpTransceiver transceiver) { - MediaStreamTrack track = transceiver.getReceiver().getTrack(); - String kind = track.getKind(); - - LOG.info("{} track added to transceiver", kind); - - if (onTrackReceived != null) { - onTrackReceived.accept(track); - } - } } } \ No newline at end of file diff --git a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/media/AudioGenerator.java b/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/media/AudioGenerator.java deleted file mode 100644 index a0ea68c..0000000 --- a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/media/AudioGenerator.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright 2025 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.examples.web.media; - -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import dev.onvoid.webrtc.media.audio.CustomAudioSource; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * A generator that produces synthetic audio samples as a continuous sine wave. - *

- * This class creates a 440 Hz (A4 note) sine wave and delivers audio frames - * at regular 10 ms intervals. The generated audio is stereo with 16-bit samples - * at a 48 kHz sample rate. The audio generator runs on a dedicated scheduled - * thread that can be started and stopped on demand. - *

- *

- * The sine wave phase is maintained between audio frames to ensure a continuous - * waveform without clicks or pops that would occur from phase discontinuities. - *

- * - * @author Alex Andres - */ -public class AudioGenerator { - - private static final Logger LOG = LoggerFactory.getLogger(AudioGenerator.class); - - /** The custom audio source that receives generated audio frames. */ - private final CustomAudioSource customAudioSource; - - /** Flag indicating whether the audio generator is running. */ - private final AtomicBoolean generatorRunning = new AtomicBoolean(false); - - /** Executor service for scheduling audio sample generation. */ - private ScheduledExecutorService executorService; - - /** Future for the scheduled audio sample generation task. */ - private ScheduledFuture generatorFuture; - - /** Default audio parameters */ - private static final int DEFAULT_BITS_PER_SAMPLE = 16; - private static final int DEFAULT_SAMPLE_RATE = 48000; - private static final int DEFAULT_CHANNELS = 2; - private static final int DEFAULT_FRAME_COUNT = 480; // 10ms at 48kHz - - /** - * Sine wave phase tracking for audio generation. - * Maintained between frames to ensure a continuous sine wave without clicks or pops. - */ - private double sinePhase = 0.0; - - - public AudioGenerator(CustomAudioSource audioSource) { - customAudioSource = audioSource; - } - - /** - * Starts the audio sample generator thread that pushes audio frames - * to the custom audio source every 10 ms. - */ - public void start() { - if (generatorRunning.get()) { - LOG.info("Audio generator is already running"); - return; - } - - executorService = Executors.newSingleThreadScheduledExecutor(); - - generatorRunning.set(true); - - generatorFuture = executorService.scheduleAtFixedRate(() -> { - if (!generatorRunning.get()) { - return; - } - - try { - // Create a buffer with audio data (silence in this case). - int bytesPerSample = DEFAULT_BITS_PER_SAMPLE / 8; - byte[] audioData = new byte[DEFAULT_FRAME_COUNT * DEFAULT_CHANNELS * bytesPerSample]; - - // Generate a pleasant sine wave at 440 Hz (A4 note). - double amplitude = 0.2; // 30% of the maximum to avoid being too loud - double frequency = 440.0; // A4 note (440 Hz) - double radiansPerSample = 2.0 * Math.PI * frequency / DEFAULT_SAMPLE_RATE; - - for (int i = 0; i < DEFAULT_FRAME_COUNT; i++) { - short sample = (short) (amplitude * Short.MAX_VALUE * Math.sin(sinePhase)); - sinePhase += radiansPerSample; - - // Keep the phase between 0 and 2Ï€. - if (sinePhase > 2.0 * Math.PI) { - sinePhase -= 2.0 * Math.PI; - } - - // Write the sample to both channels (stereo). - for (int channel = 0; channel < DEFAULT_CHANNELS; channel++) { - int index = (i * DEFAULT_CHANNELS + channel) * bytesPerSample; - // Write as little-endian (LSB first). - audioData[index] = (byte) (sample & 0xFF); - audioData[index + 1] = (byte) ((sample >> 8) & 0xFF); - } - } - - // Push the audio data to the custom audio source. - customAudioSource.pushAudio( - audioData, - DEFAULT_BITS_PER_SAMPLE, - DEFAULT_SAMPLE_RATE, - DEFAULT_CHANNELS, - DEFAULT_FRAME_COUNT - ); - } - catch (Exception e) { - LOG.error("Error in audio generator thread", e); - } - }, 0, 10, TimeUnit.MILLISECONDS); - - LOG.info("Audio generator started"); - } - - /** - * Stops the audio sample generator thread. - */ - public void stop() { - if (!generatorRunning.get()) { - return; - } - - generatorRunning.set(false); - - if (generatorFuture != null) { - generatorFuture.cancel(false); - generatorFuture = null; - } - - if (executorService != null) { - executorService.shutdown(); - try { - if (!executorService.awaitTermination(100, TimeUnit.MILLISECONDS)) { - executorService.shutdownNow(); - } - } - catch (InterruptedException e) { - executorService.shutdownNow(); - Thread.currentThread().interrupt(); - } - executorService = null; - } - - LOG.info("Audio generator stopped"); - } - -} diff --git a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/media/MediaManager.java b/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/media/MediaManager.java deleted file mode 100644 index ec62676..0000000 --- a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/media/MediaManager.java +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright 2025 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.examples.web.media; - -import java.util.List; - -import dev.onvoid.webrtc.media.audio.AudioOptions; -import dev.onvoid.webrtc.media.audio.AudioTrack; -import dev.onvoid.webrtc.media.audio.AudioTrackSink; -import dev.onvoid.webrtc.media.audio.CustomAudioSource; -import dev.onvoid.webrtc.media.video.CustomVideoSource; -import dev.onvoid.webrtc.media.video.VideoDeviceSource; -import dev.onvoid.webrtc.media.video.VideoTrack; -import dev.onvoid.webrtc.media.video.VideoTrackSink; - -import dev.onvoid.webrtc.examples.web.connection.PeerConnectionManager; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Manages media tracks for WebRTC connections, including audio and video. - * - * @author Alex Andres - */ -public class MediaManager { - - private static final Logger LOG = LoggerFactory.getLogger(MediaManager.class); - - /** The audio track managed by this class. */ - private AudioTrack audioTrack; - - /** The video track managed by this class. */ - private VideoTrack videoTrack; - - /** The custom audio source for generating audio frames. */ - private CustomAudioSource customAudioSource; - - /** The audio generator responsible for creating and pushing audio frames to the custom audio source. */ - private AudioGenerator audioGenerator; - - /** The custom video source for generating video frames. */ - private CustomVideoSource customVideoSource; - - /** The video generator responsible for creating and pushing video frames to the custom video source. */ - private VideoGenerator videoGenerator; - - - /** - * Creates a new MediaManager. - */ - public MediaManager() { - LOG.info("MediaManager created"); - } - - /** - * Creates and initializes audio and video tracks. - * - * @param peerConnectionManager The peer connection manager to use for creating tracks. - */ - public void createTracks(PeerConnectionManager peerConnectionManager) { - createAudioTrack(peerConnectionManager); - createVideoTrack(peerConnectionManager); - - // Add tracks to the peer connection. - List streamIds = List.of("stream0"); - - peerConnectionManager.addTrack(getAudioTrack(), streamIds); - peerConnectionManager.addTrack(getVideoTrack(), streamIds); - } - - /** - * Creates and initializes tracks with a custom audio source and standard video track. - * - * @param peerConnectionManager The peer connection manager to use for creating tracks. - * @param useCustomAudio Whether to use a custom audio source that can push frames. - */ - public void createTracks(PeerConnectionManager peerConnectionManager, boolean useCustomAudio) { - if (useCustomAudio) { - createCustomAudioTrack(peerConnectionManager); - } - else { - createAudioTrack(peerConnectionManager); - } - - createVideoTrack(peerConnectionManager); - - // Add tracks to the peer connection. - List streamIds = List.of("stream0"); - - peerConnectionManager.addTrack(getAudioTrack(), streamIds); - peerConnectionManager.addTrack(getVideoTrack(), streamIds); - } - - /** - * Creates and initializes tracks with options for both custom audio and video sources. - * - * @param peerConnectionManager The peer connection manager to use for creating tracks. - * @param useCustomAudio Whether to use a custom audio source that can push frames. - * @param useCustomVideo Whether to use a custom video source that can push frames. - */ - public void createTracks(PeerConnectionManager peerConnectionManager, boolean useCustomAudio, boolean useCustomVideo) { - if (useCustomAudio) { - createCustomAudioTrack(peerConnectionManager); - } - else { - createAudioTrack(peerConnectionManager); - } - - if (useCustomVideo) { - createCustomVideoTrack(peerConnectionManager); - } - else { - createVideoTrack(peerConnectionManager); - } - - // Add tracks to the peer connection. - List streamIds = List.of("stream0"); - - peerConnectionManager.addTrack(getAudioTrack(), streamIds); - peerConnectionManager.addTrack(getVideoTrack(), streamIds); - } - - /** - * Creates an audio track with default options. - */ - private void createAudioTrack(PeerConnectionManager peerConnectionManager) { - AudioOptions audioOptions = new AudioOptions(); - audioOptions.echoCancellation = true; - audioOptions.autoGainControl = true; - audioOptions.noiseSuppression = true; - - audioTrack = peerConnectionManager.createAudioTrack(audioOptions, "audio0"); - - LOG.info("Audio track created"); - } - - /** - * Creates an audio track with a custom audio source that can push audio frames. - * Also starts the audio generator thread that pushes audio frames every 10ms. - * - * @param peerConnectionManager The peer connection manager to use for creating the track. - */ - public void createCustomAudioTrack(PeerConnectionManager peerConnectionManager) { - customAudioSource = new CustomAudioSource(); - - audioTrack = peerConnectionManager.createAudioTrack(customAudioSource, "audio0"); - - // Start the audio generator. - audioGenerator = new AudioGenerator(customAudioSource); - audioGenerator.start(); - - LOG.info("Custom audio track created with audio generator"); - } - - /** - * Creates a video track using the default video device. - */ - private void createVideoTrack(PeerConnectionManager peerConnectionManager) { - VideoDeviceSource videoSource = new VideoDeviceSource(); - videoSource.start(); - - videoTrack = peerConnectionManager.createVideoTrack(videoSource, "video0"); - - LOG.info("Video track created"); - } - - /** - * Creates a video track with a custom video source that can push video frames. - * Also starts the video generator thread that pushes video frames at regular intervals. - * - * @param peerConnectionManager The peer connection manager to use for creating the track. - */ - public void createCustomVideoTrack(PeerConnectionManager peerConnectionManager) { - customVideoSource = new CustomVideoSource(); - - videoTrack = peerConnectionManager.createVideoTrack(customVideoSource, "video0"); - - // Start the video generator. - videoGenerator = new VideoGenerator(customVideoSource); - videoGenerator.start(); - - LOG.info("Custom video track created with video generator"); - } - - /** - * Gets the audio track. - * - * @return The audio track. - */ - public AudioTrack getAudioTrack() { - return audioTrack; - } - - /** - * Gets the video track. - * - * @return The video track. - */ - public VideoTrack getVideoTrack() { - return videoTrack; - } - - /** - * Adds a sink to the audio track. - * - * @param sink The sink to add. - */ - public void addAudioSink(AudioTrackSink sink) { - if (audioTrack != null) { - audioTrack.addSink(sink); - - LOG.info("Added sink to audio track"); - } - } - - /** - * Adds a sink to the video track. - * - * @param sink The sink to add. - */ - public void addVideoSink(VideoTrackSink sink) { - if (videoTrack != null) { - videoTrack.addSink(sink); - - LOG.info("Added sink to video track"); - } - } - - /** - * Disposes of all media resources. - */ - public void dispose() { - // Stop the audio generator if it's running. - if (audioGenerator != null) { - audioGenerator.stop(); - audioGenerator = null; - } - - // Stop the video generator if it's running. - if (videoGenerator != null) { - videoGenerator.stop(); - videoGenerator = null; - } - - if (audioTrack != null) { - audioTrack.dispose(); - audioTrack = null; - } - - if (videoTrack != null) { - videoTrack.dispose(); - videoTrack = null; - } - - customAudioSource = null; - customVideoSource = null; - - LOG.info("Media resources disposed"); - } -} \ No newline at end of file diff --git a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/media/VideoGenerator.java b/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/media/VideoGenerator.java deleted file mode 100644 index 950ed5d..0000000 --- a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/media/VideoGenerator.java +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright 2025 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.examples.web.media; - -import java.nio.ByteBuffer; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -import dev.onvoid.webrtc.media.video.CustomVideoSource; -import dev.onvoid.webrtc.media.video.NativeI420Buffer; -import dev.onvoid.webrtc.media.video.VideoFrame; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * A generator that produces synthetic video frames. - *

- * This class creates a color pattern that changes over time and delivers video frames - * at regular intervals (30 fps by default). The generated video is in I420 format - * with a default resolution of 640x480. The video generator runs on a dedicated scheduled - * thread that can be started and stopped on demand. - *

- * - * @author Alex Andres - */ -public class VideoGenerator { - - private static final Logger LOG = LoggerFactory.getLogger(VideoGenerator.class); - - /** The custom video source that receives generated video frames. */ - private final CustomVideoSource customVideoSource; - - /** Flag indicating whether the video generator is running. */ - private final AtomicBoolean generatorRunning = new AtomicBoolean(false); - - /** Counter for frame animation. */ - private final AtomicInteger frameCounter = new AtomicInteger(0); - - /** Executor service for scheduling video frame generation. */ - private ScheduledExecutorService executorService; - - /** Future for the scheduled video frame generation task. */ - private ScheduledFuture generatorFuture; - - /** Default video parameters */ - private static final int DEFAULT_WIDTH = 640; - private static final int DEFAULT_HEIGHT = 480; - private static final int DEFAULT_FPS = 30; - private static final int FRAME_INTERVAL_MS = 1000 / DEFAULT_FPS; - - - /** - * Creates a new VideoGenerator that will push frames to the specified video source. - * - * @param videoSource The custom video source to receive the generated frames. - */ - public VideoGenerator(CustomVideoSource videoSource) { - customVideoSource = videoSource; - } - - /** - * Starts the video frame generator thread that pushes video frames - * to the custom video source at the specified frame rate. - */ - public void start() { - if (generatorRunning.get()) { - LOG.info("Video generator is already running"); - return; - } - - executorService = Executors.newSingleThreadScheduledExecutor(); - generatorRunning.set(true); - - generatorFuture = executorService.scheduleAtFixedRate(() -> { - if (!generatorRunning.get()) { - return; - } - - try { - // Create a new video frame with a color pattern. - VideoFrame frame = generateVideoFrame(); - - // Push the frame to the custom video source. - customVideoSource.pushFrame(frame); - - // Release the frame after pushing it. - frame.release(); - - // Increment frame counter for animation. - frameCounter.incrementAndGet(); - } - catch (Exception e) { - LOG.error("Error in video generator thread", e); - } - }, 0, FRAME_INTERVAL_MS, TimeUnit.MILLISECONDS); - - LOG.info("Video generator started at {} fps", DEFAULT_FPS); - } - - /** - * Stops the video frame generator thread. - */ - public void stop() { - if (!generatorRunning.get()) { - return; - } - - generatorRunning.set(false); - - if (generatorFuture != null) { - generatorFuture.cancel(false); - generatorFuture = null; - } - - if (executorService != null) { - executorService.shutdown(); - try { - if (!executorService.awaitTermination(100, TimeUnit.MILLISECONDS)) { - executorService.shutdownNow(); - } - } - catch (InterruptedException e) { - executorService.shutdownNow(); - Thread.currentThread().interrupt(); - } - executorService = null; - } - - LOG.info("Video generator stopped"); - } - - /** - * Generates a video frame with a color pattern that changes over time. - * - * @return A new VideoFrame with the generated pattern. - */ - private VideoFrame generateVideoFrame() { - // Allocate a new I420 buffer for the frame - NativeI420Buffer buffer = NativeI420Buffer.allocate(DEFAULT_WIDTH, DEFAULT_HEIGHT); - - // Get the Y, U, V planes - ByteBuffer dataY = buffer.getDataY(); - ByteBuffer dataU = buffer.getDataU(); - ByteBuffer dataV = buffer.getDataV(); - - int strideY = buffer.getStrideY(); - int strideU = buffer.getStrideU(); - int strideV = buffer.getStrideV(); - - // Generate a color pattern - fillFrameWithPattern(dataY, dataU, dataV, strideY, strideU, strideV, frameCounter.get()); - - // Create a new video frame with the buffer and current timestamp - return new VideoFrame(buffer, System.nanoTime()); - } - - /** - * Fills the frame buffers with a color pattern. - * This creates a simple test pattern that changes over time. - * - * @param dataY The Y plane buffer. - * @param dataU The U plane buffer. - * @param dataV The V plane buffer. - * @param strideY The Y plane stride. - * @param strideU The U plane stride. - * @param strideV The V plane stride. - * @param frameCount The current frame count for animation. - */ - private void fillFrameWithPattern(ByteBuffer dataY, ByteBuffer dataU, ByteBuffer dataV, - int strideY, int strideU, int strideV, int frameCount) { - // Reset buffer positions - dataY.position(0); - dataU.position(0); - dataV.position(0); - - // Animation parameters - int animOffset = frameCount % 255; - - // Fill Y plane (luma) - for (int y = 0; y < DEFAULT_HEIGHT; y++) { - for (int x = 0; x < DEFAULT_WIDTH; x++) { - // Create a gradient pattern - byte value = (byte) ((x + y + animOffset) % 255); - dataY.put(y * strideY + x, value); - } - } - - // Fill U and V planes (chroma) - // In I420 format, U and V planes are quarter size of Y plane - for (int y = 0; y < DEFAULT_HEIGHT / 2; y++) { - for (int x = 0; x < DEFAULT_WIDTH / 2; x++) { - // Create color patterns that change over time - byte uValue = (byte) ((x * 2 + animOffset) % 255); - byte vValue = (byte) ((y * 2 + animOffset) % 255); - - dataU.put(y * strideU + x, uValue); - dataV.put(y * strideV + x, vValue); - } - } - } -} \ No newline at end of file diff --git a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/server/WebServer.java b/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/server/WebServer.java deleted file mode 100644 index 98eb42a..0000000 --- a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/server/WebServer.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2025 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.examples.web.server; - -import java.io.InputStream; -import java.security.KeyStore; - -import dev.onvoid.webrtc.examples.web.WebClientExample; - -import org.eclipse.jetty.http.pathmap.PathSpec; -import org.eclipse.jetty.server.*; -import org.eclipse.jetty.server.handler.PathMappingsHandler; -import org.eclipse.jetty.server.handler.ResourceHandler; -import org.eclipse.jetty.util.resource.ResourceFactory; -import org.eclipse.jetty.util.ssl.SslContextFactory; -import org.eclipse.jetty.websocket.server.WebSocketUpgradeHandler; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * A web server implementation using Jetty that provides both HTTPS and WebSocket functionality. - *

- * This server: - *

    - *
  • Runs on port 8443 with HTTPS only (TLS 1.2/1.3)
  • - *
  • Provides WebSocket endpoints with the "ws-signaling" protocol
  • - *
  • Serves static resources from the classpath at "/resources/web/"
  • - *
  • Uses a self-signed certificate from a bundled keystore
  • - *
- *

- * - * @author Alex Andres - */ -public class WebServer { - - static { - WebClientExample.setupLogging(); - } - - public static final Logger LOG = LoggerFactory.getLogger(WebServer.class); - - private static final int PORT = 8443; - - - public static void main(String[] args) throws Exception { - Server server = new Server(); - - // Configure HTTPS only. - HttpConfiguration httpsConfig = new HttpConfiguration(); - httpsConfig.addCustomizer(new SecureRequestCustomizer()); - - // Create the HTTP/1.1 ConnectionFactory. - HttpConnectionFactory http = new HttpConnectionFactory(httpsConfig); - - // Create the TLS ConnectionFactory, setting HTTP/1.1 as the wrapped protocol. - SslContextFactory.Server sslContextFactory = createSslContextFactory(); - SslConnectionFactory tls = new SslConnectionFactory(sslContextFactory, http.getProtocol()); - - ServerConnector httpsConnector = new ServerConnector(server, tls, http); - httpsConnector.setPort(PORT); - - // Add only HTTPS connector. - server.addConnector(httpsConnector); - - // Create WebSocket upgrade handler. - WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, container -> { - container.addMapping("/ws", (upgradeRequest, upgradeResponse, callback) -> { - if (upgradeRequest.getSubProtocols().contains("ws-signaling")) { - upgradeResponse.setAcceptedSubProtocol("ws-signaling"); - return new WebSocketHandler(); - } - return null; - }); - }); - - // Create a static resource handler. - ResourceHandler resourceHandler = new ResourceHandler(); - ResourceFactory resourceFactory = ResourceFactory.of(resourceHandler); - resourceHandler.setBaseResource(resourceFactory.newClassLoaderResource("/resources/web/")); - - // Create a path mappings handler to combine WebSocket and static content. - PathMappingsHandler pathHandler = new PathMappingsHandler(); - pathHandler.addMapping(PathSpec.from("/ws/*"), wsHandler); - pathHandler.addMapping(PathSpec.from("/"), resourceHandler); - - server.setHandler(pathHandler); - server.start(); - - LOG.info("HTTPS: https://localhost:{}", PORT); - LOG.info("WebSocket: wss://localhost:{}/ws", PORT); - LOG.info("Note: Using self-signed certificate - browsers will show security warnings"); - - server.join(); - } - - private static SslContextFactory.Server createSslContextFactory() { - SslContextFactory.Server sslContextFactory = new SslContextFactory.Server(); - - try (InputStream keystoreStream = WebServer.class.getResourceAsStream("/resources/keystore.p12")) { - if (keystoreStream == null) { - throw new IllegalArgumentException("Keystore not found in resources."); - } - - KeyStore keyStore = KeyStore.getInstance("PKCS12"); - keyStore.load(keystoreStream, "l0c4lh0s7".toCharArray()); - - sslContextFactory.setKeyStore(keyStore); - sslContextFactory.setKeyStorePassword("l0c4lh0s7"); - } - catch (Exception e) { - LOG.error("Load keystore failed", e); - } - - // Security settings. - sslContextFactory.setIncludeProtocols("TLSv1.3", "TLSv1.2"); - - return sslContextFactory; - } -} diff --git a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/server/WebSocketHandler.java b/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/server/WebSocketHandler.java deleted file mode 100644 index d4ece58..0000000 --- a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/server/WebSocketHandler.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright 2025 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.examples.web.server; - -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArraySet; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; - -import dev.onvoid.webrtc.examples.web.model.LeaveMessage; -import dev.onvoid.webrtc.examples.web.model.MessageType; -import dev.onvoid.webrtc.examples.web.model.SignalingMessage; - -import org.eclipse.jetty.websocket.api.Callback; -import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.api.annotations.*; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Handles WebSocket connections and messages for the WebRTC signaling server. - *

- * This class manages all active WebSocket sessions, processes incoming messages, - * and provides methods for broadcasting messages to connected clients. - *

- * - * @author Alex Andres - */ -@WebSocket -public class WebSocketHandler { - - private static final Logger LOG = LoggerFactory.getLogger(WebSocketHandler.class); - - /** Thread-safe set to store all active sessions. */ - private static final Set sessions = new CopyOnWriteArraySet<>(); - - /** Thread-safe map to store session to user-id mappings. */ - private static final Map sessionToUserId = new ConcurrentHashMap<>(); - - /** JSON serializer/deserializer for processing WebSocket messages. */ - private final ObjectMapper jsonMapper = new ObjectMapper(); - - - @OnWebSocketOpen - public void onOpen(Session session) { - sessions.add(session); - - LOG.info("New connection: {} (Total connections: {})", session.getRemoteSocketAddress(), sessions.size()); - } - - @OnWebSocketMessage - public void onMessage(Session session, String message) { - LOG.info("Message from {}: {}", session.getRemoteSocketAddress(), message); - - try { - JsonNode messageNode = jsonMapper.readTree(message); - String type = messageNode.path("type").asText(); - - // Check if this is a heartbeat message. - if (MessageType.HEARTBEAT.getValue().equals(type)) { - // Send heartbeat acknowledgment. - SignalingMessage heartbeatAck = new SignalingMessage("heartbeat-ack"); - String heartbeatAckJson = jsonMapper.writeValueAsString(heartbeatAck); - - sendMessage(session, heartbeatAckJson); - return; - } - - // Check if this is a join message and extract the user-id. - if (MessageType.JOIN.getValue().equals(type)) { - String userId = messageNode.path("from").asText(); - - if (userId != null && !userId.isEmpty()) { - // Store the user-id for this session. - sessionToUserId.put(session, userId); - - LOG.info("Registered user-id '{}' for session {}", userId, session.getRemoteSocketAddress()); - } - } - } - catch (JsonProcessingException e) { - LOG.error("Error parsing message type", e); - } - - // Broadcast the message to all other connected peers (excluding sender). - broadcastToOthers(session, message); - } - - @OnWebSocketClose - public void onClose(Session session, int statusCode, String reason) { - sessions.remove(session); - - LOG.info("Connection closed: {} ({}) - Status: {}", session.getRemoteSocketAddress(), reason, statusCode); - LOG.info("Remaining connections: {}", sessions.size()); - - // Notify other clients about disconnection. - try { - // Get the user-id for this session or use the socket address as a fallback. - String userId = sessionToUserId.getOrDefault(session, session.getRemoteSocketAddress().toString()); - - // Create a leave message. - LeaveMessage leaveMessage = new LeaveMessage(); - leaveMessage.setFrom(userId); - - String leaveMessageJson = jsonMapper.writeValueAsString(leaveMessage); - broadcastToAll(leaveMessageJson); - - LOG.info("Sent participant left message for user-id: {}", userId); - - // Clean up the session-to-userId mapping. - sessionToUserId.remove(session); - } - catch (JsonProcessingException e) { - LOG.error("Error creating participant left message", e); - } - } - - @OnWebSocketError - public void onError(Session session, Throwable error) { - LOG.error("WebSocket error for {}", session.getRemoteSocketAddress(), error); - } - - /** - * Broadcasts a message to all connected peers except the sender. - * - * @param sender the session of the sender. - * @param message the message to broadcast. - */ - private void broadcastToOthers(Session sender, String message) { - sessions.stream() - .filter(Session::isOpen) - .filter(session -> !session.equals(sender)) - .forEach(session -> sendMessage(session, message)); - } - - /** - * Broadcasts a message to all connected peers. - * - * @param message the message to broadcast. - */ - private void broadcastToAll(String message) { - sessions.stream() - .filter(Session::isOpen) - .forEach(session -> sendMessage(session, message)); - } - - private void sendMessage(Session session, String message) { - session.sendText(message, Callback.from(() -> {}, throwable -> { - LOG.error("Error sending message to session: {}", throwable.getMessage()); - // Remove broken sessions. - sessions.remove(session); - })); - } -} diff --git a/webrtc-jni/src/main/cpp/CMakeLists.txt b/webrtc-jni/src/main/cpp/CMakeLists.txt index 82f72ae..8e8b7b3 100644 --- a/webrtc-jni/src/main/cpp/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/CMakeLists.txt @@ -50,29 +50,11 @@ add_subdirectory(dependencies/jni-voithos) file(GLOB SOURCES_ROOT "src/*.cpp") file(GLOB SOURCES_API "src/api/*.cpp") -file(GLOB SOURCES_API_AUDIO "src/api/audio/*.cpp") -file(GLOB SOURCES_MEDIA "src/media/*.cpp") -file(GLOB SOURCES_MEDIA_AUDIO "src/media/audio/*.cpp") -file(GLOB SOURCES_MEDIA_AUDIO_OS "src/media/audio/${SOURCE_TARGET}/*.cpp") -file(GLOB SOURCES_MEDIA_VIDEO "src/media/video/*.cpp") -file(GLOB SOURCES_MEDIA_VIDEO_DESKTOP "src/media/video/desktop/*.cpp") -file(GLOB SOURCES_MEDIA_VIDEO_DESKTOP_OS "src/media/video/desktop/${SOURCE_TARGET}/*.cpp") -file(GLOB SOURCES_MEDIA_VIDEO_OS "src/media/video/${SOURCE_TARGET}/*.cpp") -file(GLOB SOURCES_PLATFORM "src/platform/${SOURCE_TARGET}/*.cpp") file(GLOB SOURCES_RTC "src/rtc/*.cpp") list(APPEND SOURCES ${SOURCES_ROOT} ${SOURCES_API} - ${SOURCES_API_AUDIO} - ${SOURCES_MEDIA} - ${SOURCES_MEDIA_AUDIO} - ${SOURCES_MEDIA_AUDIO_OS} - ${SOURCES_MEDIA_VIDEO} - ${SOURCES_MEDIA_VIDEO_DESKTOP} - ${SOURCES_MEDIA_VIDEO_DESKTOP_OS} - ${SOURCES_MEDIA_VIDEO_OS} - ${SOURCES_PLATFORM} ${SOURCES_RTC} ) @@ -85,7 +67,6 @@ target_include_directories(${PROJECT_NAME} PRIVATE include include/api - include/media include/rtc ) @@ -102,7 +83,7 @@ target_link_libraries(${PROJECT_NAME} webrtc) if(APPLE) set_source_files_properties(${SOURCES} PROPERTIES COMPILE_FLAGS "-x objective-c++") target_link_options(${PROJECT_NAME} PRIVATE "-ObjC") - target_link_libraries(${PROJECT_NAME} "-framework Foundation" "-framework AVFoundation" "-framework CoreMedia" "-framework CoreAudio" "-framework IOKit" "-framework CoreVideo" "-framework VideoToolbox" "-framework QuartzCore") + target_link_libraries(${PROJECT_NAME} "-framework Foundation" "-framework IOKit") elseif(LINUX) if(NOT TARGET_CPU MATCHES "^arm") set(CXX_LIBS "-static-libgcc -stdlib=libc++ -lc++ -lc++abi") @@ -110,10 +91,9 @@ elseif(LINUX) set(CXX_LIBS "-static-libgcc") endif() - target_link_libraries(${PROJECT_NAME} ${CXX_LIBS} udev) - target_link_libraries(${PROJECT_NAME} dl) + target_link_libraries(${PROJECT_NAME} ${CXX_LIBS}) elseif(WIN32) - target_link_libraries(${PROJECT_NAME} dwmapi.lib mf.lib mfreadwrite.lib mfplat.lib mfuuid.lib shcore.lib) + target_link_libraries(${PROJECT_NAME} shcore.lib) endif() install(TARGETS ${PROJECT_NAME} diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt index a11a7b5..ac48c71 100644 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt @@ -164,19 +164,14 @@ if(APPLE) ${TARGET_INC_DIR}/sdk/objc ${TARGET_INC_DIR}/sdk/objc/base ) - target_compile_definitions(${PROJECT_NAME} PUBLIC WEBRTC_MAC WEBRTC_POSIX WEBRTC_USE_H264) - target_link_libraries(${PROJECT_NAME} "-framework Foundation" "-framework AVFoundation" "-framework CoreGraphics" "-framework CoreAudio" "-framework CoreVideo" "-framework ScreenCaptureKit" "-framework AudioToolbox" "-framework IOSurface" "-framework ApplicationServices" "-framework AppKit") + target_compile_definitions(${PROJECT_NAME} PUBLIC WEBRTC_MAC WEBRTC_POSIX) + target_link_libraries(${PROJECT_NAME} "-framework Foundation" "-framework IOKit") elseif(LINUX) - # Find DBus - find_package(PkgConfig QUIET REQUIRED) # Include functions provided by PkgConfig module. - pkg_check_modules(DBUS REQUIRED dbus-1) - target_include_directories(${PROJECT_NAME} PUBLIC ${DBUS_INCLUDE_DIRS}) - target_compile_definitions(${PROJECT_NAME} PUBLIC WEBRTC_LINUX WEBRTC_POSIX WEBRTC_USE_H264) - target_link_libraries(${PROJECT_NAME} X11 Xfixes Xrandr Xcomposite dbus-1) + target_compile_definitions(${PROJECT_NAME} PUBLIC WEBRTC_LINUX WEBRTC_POSIX) elseif(WIN32) - target_compile_definitions(${PROJECT_NAME} PUBLIC WEBRTC_WIN WEBRTC_USE_H264 NOMINMAX WIN32_LEAN_AND_MEAN NDEBUG) - target_link_libraries(${PROJECT_NAME} D3D11 DXGI user32 gdi32 iphlpapi dmoguids msdmo secur32 strmiids winmm wmcodecdspuuid ws2_32) + target_compile_definitions(${PROJECT_NAME} PUBLIC WEBRTC_WIN NOMINMAX WIN32_LEAN_AND_MEAN NDEBUG) + target_link_libraries(${PROJECT_NAME} user32 iphlpapi secur32 ws2_32) endif() if(EXISTS "${WEBRTC_LIB_PATH}" OR EXISTS "${WEBRTC_LIB_PATH_INSTALLED}") @@ -265,9 +260,13 @@ rtc_enable_protobuf=false \ rtc_build_examples=false \ rtc_include_tests=false \ use_rtti=true \ -rtc_use_h264=true \ +rtc_use_h264=false \ ffmpeg_branding=\"Chrome\" \ -symbol_level=0") +symbol_level=0 \ +rtc_use_x11=false \ +use_dbus=false \ +use_udev=false \ +rtc_use_pulseaudio=false") if(APPLE) set(COMPILE_ARGS "${COMPILE_ARGS} mac_deployment_target=\"${CMAKE_OSX_DEPLOYMENT_TARGET}\"") diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/patches/macos/patch_for_mac_deviceId.patch b/webrtc-jni/src/main/cpp/dependencies/webrtc/patches/macos/patch_for_mac_deviceId.patch deleted file mode 100644 index af35cef..0000000 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/patches/macos/patch_for_mac_deviceId.patch +++ /dev/null @@ -1,32 +0,0 @@ -Subject: [PATCH] patch for mac deviceId ---- -Index: modules/audio_device/mac/audio_device_mac.cc -IDEA additional info: -Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP -<+>UTF-8 -=================================================================== -diff --git a/modules/audio_device/mac/audio_device_mac.cc b/modules/audio_device/mac/audio_device_mac.cc ---- a/modules/audio_device/mac/audio_device_mac.cc (revision e4445e46a910eb407571ec0b0b8b7043562678cf) -+++ b/modules/audio_device/mac/audio_device_mac.cc (date 1757498230183) -@@ -834,6 +834,10 @@ - - if (guid != NULL) { - memset(guid, 0, kAdmMaxGuidSize); -+ AudioDeviceID deviceIds[MaxNumberDevices]; -+ int numberDevices = GetNumberDevices(kAudioDevicePropertyScopeOutput, deviceIds, MaxNumberDevices); -+ std::string deviceId = std::to_string(deviceIds[index]); -+ deviceId.copy(guid, kAdmMaxGuidSize); - } - - return GetDeviceName(kAudioDevicePropertyScopeOutput, index, -@@ -853,6 +857,10 @@ - - if (guid != NULL) { - memset(guid, 0, kAdmMaxGuidSize); -+ AudioDeviceID deviceIds[MaxNumberDevices]; -+ int numberDevices = GetNumberDevices(kAudioDevicePropertyScopeInput, deviceIds, MaxNumberDevices); -+ std::string deviceId = std::to_string(deviceIds[index]); -+ deviceId.copy(guid, kAdmMaxGuidSize); - } - - return GetDeviceName(kAudioDevicePropertyScopeInput, index, diff --git a/webrtc-jni/src/main/cpp/include/JNI_AudioConverter.h b/webrtc-jni/src/main/cpp/include/JNI_AudioConverter.h deleted file mode 100644 index f29c41b..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_AudioConverter.h +++ /dev/null @@ -1,37 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_media_audio_AudioConverter */ - -#ifndef _Included_dev_onvoid_webrtc_media_audio_AudioConverter -#define _Included_dev_onvoid_webrtc_media_audio_AudioConverter -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_media_audio_AudioConverter - * Method: dispose - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioConverter_dispose - (JNIEnv*, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioConverter - * Method: initialize - * Signature: (IIII)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioConverter_initialize - (JNIEnv*, jobject, jint, jint, jint, jint); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioConverter - * Method: convertInternal - * Signature: ([BI[BI)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioConverter_convertInternal - (JNIEnv*, jobject, jbyteArray, jint, jbyteArray, jint); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/webrtc-jni/src/main/cpp/include/JNI_AudioDeviceModule.h b/webrtc-jni/src/main/cpp/include/JNI_AudioDeviceModule.h deleted file mode 100644 index 888cc99..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_AudioDeviceModule.h +++ /dev/null @@ -1,21 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_media_audio_AudioDeviceModule */ - -#ifndef _Included_dev_onvoid_webrtc_media_audio_AudioDeviceModule -#define _Included_dev_onvoid_webrtc_media_audio_AudioDeviceModule -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModule - * Method: initialize - * Signature: (Ldev/onvoid/webrtc/media/audio/AudioLayer;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModule_initialize - (JNIEnv *, jobject, jobject); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/webrtc-jni/src/main/cpp/include/JNI_AudioDeviceModuleBase.h b/webrtc-jni/src/main/cpp/include/JNI_AudioDeviceModuleBase.h deleted file mode 100644 index b1f28de..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_AudioDeviceModuleBase.h +++ /dev/null @@ -1,229 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase */ - -#ifndef _Included_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase -#define _Included_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase - * Method: initPlayout - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_initPlayout - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase - * Method: stopPlayout - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_stopPlayout - (JNIEnv*, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase - * Method: startPlayout - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_startPlayout - (JNIEnv*, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase - * Method: initRecording - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_initRecording - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase - * Method: stopRecording - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_stopRecording - (JNIEnv*, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase - * Method: startRecording - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_startRecording - (JNIEnv*, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase - * Method: getPlayoutDevices - * Signature: ()Ljava/util/List; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_getPlayoutDevices - (JNIEnv*, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase - * Method: getRecordingDevices - * Signature: ()Ljava/util/List; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_getRecordingDevices - (JNIEnv*, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase - * Method: setPlayoutDevice - * Signature: (Ldev/onvoid/webrtc/media/audio/AudioDevice;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_setPlayoutDevice - (JNIEnv *, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase - * Method: setRecordingDevice - * Signature: (Ldev/onvoid/webrtc/media/audio/AudioDevice;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_setRecordingDevice - (JNIEnv *, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase - * Method: isSpeakerMuted - * Signature: ()Z - */ - JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_isSpeakerMuted - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase - * Method: isMicrophoneMuted - * Signature: ()Z - */ - JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_isMicrophoneMuted - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase - * Method: getSpeakerVolume - * Signature: ()I - */ - JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_getSpeakerVolume - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase - * Method: getMaxSpeakerVolume - * Signature: ()I - */ - JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_getMaxSpeakerVolume - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase - * Method: getMinSpeakerVolume - * Signature: ()I - */ - JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_getMinSpeakerVolume - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase - * Method: getMicrophoneVolume - * Signature: ()I - */ - JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_getMicrophoneVolume - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase - * Method: getMaxMicrophoneVolume - * Signature: ()I - */ - JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_getMaxMicrophoneVolume - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase - * Method: getMinMicrophoneVolume - * Signature: ()I - */ - JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_getMinMicrophoneVolume - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase - * Method: setSpeakerVolume - * Signature: (I)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_setSpeakerVolume - (JNIEnv *, jobject, jint); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase - * Method: setSpeakerMute - * Signature: (Z)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_setSpeakerMute - (JNIEnv *, jobject, jboolean); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase - * Method: setMicrophoneVolume - * Signature: (I)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_setMicrophoneVolume - (JNIEnv *, jobject, jint); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase - * Method: setMicrophoneMute - * Signature: (Z)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_setMicrophoneMute - (JNIEnv *, jobject, jboolean); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase - * Method: addSinkInternal - * Signature: (Ldev/onvoid/webrtc/media/audio/AudioSink;)J - */ - JNIEXPORT jlong JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_addSinkInternal - (JNIEnv*, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase - * Method: removeSinkInternal - * Signature: (J)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_removeSinkInternal - (JNIEnv*, jobject, jlong); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase - * Method: addSourceInternal - * Signature: (Ldev/onvoid/webrtc/media/audio/AudioSource;)J - */ - JNIEXPORT jlong JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_addSourceInternal - (JNIEnv*, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase - * Method: removeSourceInternal - * Signature: (J)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_removeSourceInternal - (JNIEnv*, jobject, jlong); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase - * Method: disposeInternal - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_disposeInternal - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/webrtc-jni/src/main/cpp/include/JNI_AudioProcessing.h b/webrtc-jni/src/main/cpp/include/JNI_AudioProcessing.h deleted file mode 100644 index 8e8644e..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_AudioProcessing.h +++ /dev/null @@ -1,77 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_media_audio_AudioProcessing */ - -#ifndef _Included_dev_onvoid_webrtc_media_audio_AudioProcessing -#define _Included_dev_onvoid_webrtc_media_audio_AudioProcessing -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_media_audio_AudioProcessing - * Method: applyConfig - * Signature: (Ldev/onvoid/webrtc/media/audio/AudioProcessingConfig;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_applyConfig - (JNIEnv*, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioProcessing - * Method: setStreamDelayMs - * Signature: (I)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_setStreamDelayMs - (JNIEnv*, jobject, jint); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioProcessing - * Method: getStreamDelayMs - * Signature: ()I - */ - JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_getStreamDelayMs - (JNIEnv*, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioProcessing - * Method: processStream - * Signature: ([BLdev/onvoid/webrtc/media/audio/AudioProcessingStreamConfig;Ldev/onvoid/webrtc/media/audio/AudioProcessingStreamConfig;[B)I - */ - JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_processStream - (JNIEnv*, jobject, jbyteArray, jobject, jobject, jbyteArray); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioProcessing - * Method: processReverseStream - * Signature: ([BLdev/onvoid/webrtc/media/audio/AudioProcessingStreamConfig;Ldev/onvoid/webrtc/media/audio/AudioProcessingStreamConfig;[B)I - */ - JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_processReverseStream - (JNIEnv*, jobject, jbyteArray, jobject, jobject, jbyteArray); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioProcessing - * Method: dispose - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_dispose - (JNIEnv*, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioProcessing - * Method: initialize - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_initialize - (JNIEnv*, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioProcessing - * Method: updateStats - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_updateStats - (JNIEnv*, jobject); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/webrtc-jni/src/main/cpp/include/JNI_AudioResampler.h b/webrtc-jni/src/main/cpp/include/JNI_AudioResampler.h deleted file mode 100644 index d667248..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_AudioResampler.h +++ /dev/null @@ -1,37 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_media_audio_AudioResampler */ - -#ifndef _Included_dev_onvoid_webrtc_media_audio_AudioResampler -#define _Included_dev_onvoid_webrtc_media_audio_AudioResampler -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_media_audio_AudioResampler - * Method: dispose - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioResampler_dispose - (JNIEnv*, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioResampler - * Method: initialize - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioResampler_initialize - (JNIEnv*, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioResampler - * Method: resample - * Signature: ([BI[BII)I - */ - JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioResampler_resampleInternal - (JNIEnv*, jobject, jbyteArray, jint, jbyteArray, jint, jint); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/webrtc-jni/src/main/cpp/include/JNI_AudioTrack.h b/webrtc-jni/src/main/cpp/include/JNI_AudioTrack.h deleted file mode 100644 index 8261a1f..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_AudioTrack.h +++ /dev/null @@ -1,37 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_media_audio_AudioTrack */ - -#ifndef _Included_dev_onvoid_webrtc_media_audio_AudioTrack -#define _Included_dev_onvoid_webrtc_media_audio_AudioTrack -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_media_audio_AudioTrack - * Method: getSignalLevel - * Signature: ()I - */ - JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioTrack_getSignalLevel - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioTrack - * Method: addSinkInternal - * Signature: (Ldev/onvoid/webrtc/media/audio/AudioTrackSink;)J - */ - JNIEXPORT jlong JNICALL Java_dev_onvoid_webrtc_media_audio_AudioTrack_addSinkInternal - (JNIEnv *, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_AudioTrack - * Method: removeSinkInternal - * Signature: (J)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioTrack_removeSinkInternal - (JNIEnv *, jobject, jlong); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/webrtc-jni/src/main/cpp/include/JNI_CustomAudioSource.h b/webrtc-jni/src/main/cpp/include/JNI_CustomAudioSource.h deleted file mode 100644 index 2355fe2..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_CustomAudioSource.h +++ /dev/null @@ -1,45 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_media_audio_CustomAudioSource */ - -#ifndef _Included_dev_onvoid_webrtc_media_audio_CustomAudioSource -#define _Included_dev_onvoid_webrtc_media_audio_CustomAudioSource -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_media_audio_CustomAudioSource - * Method: initialize - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_CustomAudioSource_initialize - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_CustomAudioSource - * Method: initializeWithClock - * Signature: (Ldev/onvoid/webrtc/media/SyncClock;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_CustomAudioSource_initializeWithClock - (JNIEnv *, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_CustomAudioSource - * Method: dispose - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_CustomAudioSource_dispose - (JNIEnv*, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_CustomAudioSource - * Method: pushAudio - * Signature: ([BIIII)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_CustomAudioSource_pushAudio - (JNIEnv *, jobject, jbyteArray, jint, jint, jint, jint); - -#ifdef __cplusplus -} -#endif -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/JNI_CustomVideoSource.h b/webrtc-jni/src/main/cpp/include/JNI_CustomVideoSource.h deleted file mode 100644 index 0b6de8a..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_CustomVideoSource.h +++ /dev/null @@ -1,45 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_media_video_CustomVideoSource */ - -#ifndef _Included_dev_onvoid_webrtc_media_video_CustomVideoSource -#define _Included_dev_onvoid_webrtc_media_video_CustomVideoSource -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_media_video_CustomVideoSource - * Method: initialize - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_CustomVideoSource_initialize - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_video_CustomVideoSource - * Method: initializeWithClock - * Signature: (Ldev/onvoid/webrtc/media/SyncClock;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_CustomVideoSource_initializeWithClock - (JNIEnv *, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_media_video_CustomVideoSource - * Method: dispose - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_CustomVideoSource_dispose - (JNIEnv*, jobject); - - /* - * Class: dev_onvoid_webrtc_media_video_CustomVideoSource - * Method: pushFrame - * Signature: (Ldev/onvoid/webrtc/media/video/VideoFrame;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_CustomVideoSource_pushFrame - (JNIEnv *, jobject, jobject); - -#ifdef __cplusplus -} -#endif -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/JNI_DesktopCapturer.h b/webrtc-jni/src/main/cpp/include/JNI_DesktopCapturer.h deleted file mode 100644 index a9e46ae..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_DesktopCapturer.h +++ /dev/null @@ -1,69 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_media_video_desktop_DesktopCapturer */ - -#ifndef _Included_dev_onvoid_webrtc_media_video_desktop_DesktopCapturer -#define _Included_dev_onvoid_webrtc_media_video_desktop_DesktopCapturer -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_media_video_desktop_DesktopCapturer - * Method: dispose - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_desktop_DesktopCapturer_dispose - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_video_desktop_DesktopCapturer - * Method: getDesktopSources - * Signature: ()Ljava/util/List; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_video_desktop_DesktopCapturer_getDesktopSources - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_video_desktop_DesktopCapturer - * Method: selectSource - * Signature: (Ldev/onvoid/webrtc/media/video/desktop/DesktopSource;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_desktop_DesktopCapturer_selectSource - (JNIEnv *, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_media_video_desktop_DesktopCapturer - * Method: setFocusSelectedSource - * Signature: (Z)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_desktop_DesktopCapturer_setFocusSelectedSource - (JNIEnv*, jobject, jboolean); - - /* - * Class: dev_onvoid_webrtc_media_video_desktop_DesktopCapturer - * Method: setMaxFrameRate - * Signature: (I)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_desktop_DesktopCapturer_setMaxFrameRate - (JNIEnv*, jobject, jint); - - /* - * Class: dev_onvoid_webrtc_media_video_desktop_DesktopCapturer - * Method: start - * Signature: (Ldev/onvoid/webrtc/media/video/desktop/DesktopCaptureCallback;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_desktop_DesktopCapturer_start - (JNIEnv *, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_media_video_desktop_DesktopCapturer - * Method: captureFrame - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_desktop_DesktopCapturer_captureFrame - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/webrtc-jni/src/main/cpp/include/JNI_HeadlessAudioDeviceModule.h b/webrtc-jni/src/main/cpp/include/JNI_HeadlessAudioDeviceModule.h deleted file mode 100644 index 075fc21..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_HeadlessAudioDeviceModule.h +++ /dev/null @@ -1,22 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_media_audio_HeadlessAudioDeviceModule */ - -#ifndef _Included_dev_onvoid_webrtc_media_audio_HeadlessAudioDeviceModule -#define _Included_dev_onvoid_webrtc_media_audio_HeadlessAudioDeviceModule -#ifdef __cplusplus -extern "C" { -#endif - - /* - * Class: dev_onvoid_webrtc_media_audio_HeadlessAudioDeviceModule - * Method: initialize - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_HeadlessAudioDeviceModule_initialize - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/webrtc-jni/src/main/cpp/include/JNI_MediaDevices.h b/webrtc-jni/src/main/cpp/include/JNI_MediaDevices.h deleted file mode 100644 index fb7d0ed..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_MediaDevices.h +++ /dev/null @@ -1,77 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_media_MediaDevices */ - -#ifndef _Included_dev_onvoid_webrtc_media_MediaDevices -#define _Included_dev_onvoid_webrtc_media_MediaDevices -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_media_MediaDevices - * Method: addDeviceChangeListener - * Signature: (Ldev/onvoid/webrtc/media/DeviceChangeListener;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_MediaDevices_addDeviceChangeListener - (JNIEnv*, jclass, jobject); - - /* - * Class: dev_onvoid_webrtc_media_MediaDevices - * Method: removeDeviceChangeListener - * Signature: (Ldev/onvoid/webrtc/media/DeviceChangeListener;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_MediaDevices_removeDeviceChangeListener - (JNIEnv*, jclass, jobject); - - /* - * Class: dev_onvoid_webrtc_media_MediaDevices - * Method: getDefaultAudioRenderDevice - * Signature: ()Ldev/onvoid/webrtc/media/audio/AudioDevice; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_MediaDevices_getDefaultAudioRenderDevice - (JNIEnv*, jclass); - - /* - * Class: dev_onvoid_webrtc_media_MediaDevices - * Method: getDefaultAudioCaptureDevice - * Signature: ()Ldev/onvoid/webrtc/media/audio/AudioDevice; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_MediaDevices_getDefaultAudioCaptureDevice - (JNIEnv*, jclass); - - /* - * Class: dev_onvoid_webrtc_media_MediaDevices - * Method: getAudioRenderDevices - * Signature: ()Ljava/util/List; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_MediaDevices_getAudioRenderDevices - (JNIEnv*, jclass); - - /* - * Class: dev_onvoid_webrtc_media_MediaDevices - * Method: getAudioCaptureDevices - * Signature: ()Ljava/util/List; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_MediaDevices_getAudioCaptureDevices - (JNIEnv*, jclass); - - /* - * Class: dev_onvoid_webrtc_media_MediaDevices - * Method: getVideoCaptureDevices - * Signature: ()Ljava/util/List; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_MediaDevices_getVideoCaptureDevices - (JNIEnv*, jclass); - - /* - * Class: dev_onvoid_webrtc_media_MediaDevices - * Method: getVideoCaptureCapabilities - * Signature: (Ldev/onvoid/webrtc/media/video/VideoDevice;)Ljava/util/List; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_MediaDevices_getVideoCaptureCapabilities - (JNIEnv*, jclass, jobject); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/webrtc-jni/src/main/cpp/include/JNI_MediaSource.h b/webrtc-jni/src/main/cpp/include/JNI_MediaSource.h deleted file mode 100644 index 5a015e7..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_MediaSource.h +++ /dev/null @@ -1,21 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_media_MediaSource */ - -#ifndef _Included_dev_onvoid_webrtc_media_MediaSource -#define _Included_dev_onvoid_webrtc_media_MediaSource -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_media_MediaSource - * Method: getState - * Signature: ()Ldev/onvoid/webrtc/media/MediaSource/State; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_MediaSource_getState - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/webrtc-jni/src/main/cpp/include/JNI_MediaStream.h b/webrtc-jni/src/main/cpp/include/JNI_MediaStream.h deleted file mode 100644 index 8d10318..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_MediaStream.h +++ /dev/null @@ -1,61 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_media_MediaStream */ - -#ifndef _Included_dev_onvoid_webrtc_media_MediaStream -#define _Included_dev_onvoid_webrtc_media_MediaStream -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_media_MediaStream - * Method: id - * Signature: ()Ljava/lang/String; - */ - JNIEXPORT jstring JNICALL Java_dev_onvoid_webrtc_media_MediaStream_id - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_MediaStream - * Method: getAudioTracks - * Signature: ()[Ldev/onvoid/webrtc/media/audio/AudioTrack; - */ - JNIEXPORT jobjectArray JNICALL Java_dev_onvoid_webrtc_media_MediaStream_getAudioTracks - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_MediaStream - * Method: getVideoTracks - * Signature: ()[Ldev/onvoid/webrtc/media/video/VideoTrack; - */ - JNIEXPORT jobjectArray JNICALL Java_dev_onvoid_webrtc_media_MediaStream_getVideoTracks - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_MediaStream - * Method: addTrack - * Signature: (Ldev/onvoid/webrtc/media/MediaStreamTrack;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_MediaStream_addTrack - (JNIEnv *, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_media_MediaStream - * Method: removeTrack - * Signature: (Ldev/onvoid/webrtc/media/MediaStreamTrack;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_MediaStream_removeTrack - (JNIEnv *, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_media_MediaStream - * Method: dispose - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_MediaStream_dispose - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/webrtc-jni/src/main/cpp/include/JNI_MediaStreamTrack.h b/webrtc-jni/src/main/cpp/include/JNI_MediaStreamTrack.h deleted file mode 100644 index 01e440f..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_MediaStreamTrack.h +++ /dev/null @@ -1,93 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_media_MediaStreamTrack */ - -#ifndef _Included_dev_onvoid_webrtc_media_MediaStreamTrack -#define _Included_dev_onvoid_webrtc_media_MediaStreamTrack -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_media_MediaStreamTrack - * Method: dispose - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_MediaStreamTrack_dispose - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_MediaStreamTrack - * Method: getKind - * Signature: ()Ljava/lang/String; - */ - JNIEXPORT jstring JNICALL Java_dev_onvoid_webrtc_media_MediaStreamTrack_getKind - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_MediaStreamTrack - * Method: getId - * Signature: ()Ljava/lang/String; - */ - JNIEXPORT jstring JNICALL Java_dev_onvoid_webrtc_media_MediaStreamTrack_getId - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_MediaStreamTrack - * Method: isEnabled - * Signature: ()Z - */ - JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_media_MediaStreamTrack_isEnabled - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_MediaStreamTrack - * Method: setEnabled - * Signature: (Z)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_MediaStreamTrack_setEnabled - (JNIEnv *, jobject, jboolean); - - /* - * Class: dev_onvoid_webrtc_media_MediaStreamTrack - * Method: getState - * Signature: ()Ldev/onvoid/webrtc/media/MediaStreamTrackState; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_MediaStreamTrack_getState - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_MediaStreamTrack - * Method: addEndedEventListener - * Signature: (Ljava/lang/Runnable;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_MediaStreamTrack_addEndedEventListener - (JNIEnv*, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_media_MediaStreamTrack - * Method: removeEndedEventListener - * Signature: (Ljava/lang/Runnable;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_MediaStreamTrack_removeEndedEventListener - (JNIEnv*, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_media_MediaStreamTrack - * Method: addMuteEventListener - * Signature: (Ljava/util/function/Consumer;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_MediaStreamTrack_addMuteEventListener - (JNIEnv*, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_media_MediaStreamTrack - * Method: removeMuteEventListener - * Signature: (Ljava/util/function/Consumer;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_MediaStreamTrack_removeMuteEventListener - (JNIEnv*, jobject, jobject); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/webrtc-jni/src/main/cpp/include/JNI_NativeI420Buffer.h b/webrtc-jni/src/main/cpp/include/JNI_NativeI420Buffer.h deleted file mode 100644 index 3998484..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_NativeI420Buffer.h +++ /dev/null @@ -1,37 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_media_video_NativeI420Buffer */ - -#ifndef _Included_dev_onvoid_webrtc_media_video_NativeI420Buffer -#define _Included_dev_onvoid_webrtc_media_video_NativeI420Buffer -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_media_video_NativeI420Buffer - * Method: allocate - * Signature: (II)Ldev/onvoid/webrtc/media/video/NativeI420Buffer; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_video_NativeI420Buffer_allocate - (JNIEnv *, jclass, jint, jint); - - /* - * Class: dev_onvoid_webrtc_media_video_NativeI420Buffer - * Method: copy - * Signature: (IILjava/nio/ByteBuffer;ILjava/nio/ByteBuffer;ILjava/nio/ByteBuffer;I)Ldev/onvoid/webrtc/media/video/NativeI420Buffer; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_video_NativeI420Buffer_copy - (JNIEnv*, jclass, jint, jint, jobject, jint, jobject, jint, jobject, jint); - - /* - * Class: dev_onvoid_webrtc_media_video_NativeI420Buffer - * Method: cropAndScale - * Signature: (Ljava/nio/ByteBuffer;ILjava/nio/ByteBuffer;ILjava/nio/ByteBuffer;IIIIILjava/nio/ByteBuffer;ILjava/nio/ByteBuffer;ILjava/nio/ByteBuffer;III)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_NativeI420Buffer_cropAndScale - (JNIEnv *, jclass, jobject, jint, jobject, jint, jobject, jint, jint, jint, jint, jint, jobject, jint, jobject, jint, jobject, jint, jint, jint); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/webrtc-jni/src/main/cpp/include/JNI_PeerConnectionFactory.h b/webrtc-jni/src/main/cpp/include/JNI_PeerConnectionFactory.h index 91d0ad6..351bd93 100644 --- a/webrtc-jni/src/main/cpp/include/JNI_PeerConnectionFactory.h +++ b/webrtc-jni/src/main/cpp/include/JNI_PeerConnectionFactory.h @@ -7,29 +7,6 @@ #ifdef __cplusplus extern "C" { #endif - /* - * Class: dev_onvoid_webrtc_PeerConnectionFactory - * Method: createAudioSource - * Signature: (Ldev/onvoid/webrtc/media/audio/AudioOptions;)Ldev/onvoid/webrtc/media/audio/AudioTrackSource; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_createAudioSource - (JNIEnv *, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_PeerConnectionFactory - * Method: createAudioTrack - * Signature: (Ljava/lang/String;Ldev/onvoid/webrtc/media/audio/AudioTrackSource;)Ldev/onvoid/webrtc/media/audio/AudioTrack; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_createAudioTrack - (JNIEnv *, jobject, jstring, jobject); - - /* - * Class: dev_onvoid_webrtc_PeerConnectionFactory - * Method: createVideoTrack - * Signature: (Ljava/lang/String;Ldev/onvoid/webrtc/media/video/VideoTrackSource;)Ldev/onvoid/webrtc/media/video/VideoTrack; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_createVideoTrack - (JNIEnv *, jobject, jstring, jobject); /* * Class: dev_onvoid_webrtc_PeerConnectionFactory @@ -39,22 +16,6 @@ extern "C" { JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_createPeerConnection (JNIEnv *, jobject, jobject, jobject); - /* - * Class: dev_onvoid_webrtc_PeerConnectionFactory - * Method: getRtpReceiverCapabilities - * Signature: (Ldev/onvoid/webrtc/media/MediaType;)Ldev/onvoid/webrtc/RTCRtpCapabilities; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_getRtpReceiverCapabilities - (JNIEnv *, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_PeerConnectionFactory - * Method: getRtpSenderCapabilities - * Signature: (Ldev/onvoid/webrtc/media/MediaType;)Ldev/onvoid/webrtc/RTCRtpCapabilities; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_getRtpSenderCapabilities - (JNIEnv *, jobject, jobject); - /* * Class: dev_onvoid_webrtc_PeerConnectionFactory * Method: dispose diff --git a/webrtc-jni/src/main/cpp/include/JNI_PowerManagement.h b/webrtc-jni/src/main/cpp/include/JNI_PowerManagement.h deleted file mode 100644 index f55be85..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_PowerManagement.h +++ /dev/null @@ -1,29 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_media_video_desktop_ScreenSaver */ - -#ifndef _Included_dev_onvoid_webrtc_media_video_desktop_ScreenSaver -#define _Included_dev_onvoid_webrtc_media_video_desktop_ScreenSaver -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_media_video_desktop_PowerManagement - * Method: enableUserActivity - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_desktop_PowerManagement_enableUserActivity - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_video_desktop_PowerManagement - * Method: disableUserActivity - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_desktop_PowerManagement_disableUserActivity - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/webrtc-jni/src/main/cpp/include/JNI_RTCDtmfSender.h b/webrtc-jni/src/main/cpp/include/JNI_RTCDtmfSender.h deleted file mode 100644 index 6a25bb5..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_RTCDtmfSender.h +++ /dev/null @@ -1,69 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_RTCDtmfSender */ - -#ifndef _Included_dev_onvoid_webrtc_RTCDtmfSender -#define _Included_dev_onvoid_webrtc_RTCDtmfSender -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_RTCDtmfSender - * Method: canInsertDtmf - * Signature: ()Z - */ - JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_RTCDtmfSender_canInsertDtmf - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCDtmfSender - * Method: insertDtmf - * Signature: (Ljava/lang/String;II)Z - */ - JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_RTCDtmfSender_insertDtmf - (JNIEnv *, jobject, jstring, jint, jint); - - /* - * Class: dev_onvoid_webrtc_RTCDtmfSender - * Method: tones - * Signature: ()Ljava/lang/String; - */ - JNIEXPORT jstring JNICALL Java_dev_onvoid_webrtc_RTCDtmfSender_tones - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCDtmfSender - * Method: duration - * Signature: ()I - */ - JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_RTCDtmfSender_duration - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCDtmfSender - * Method: interToneGap - * Signature: ()I - */ - JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_RTCDtmfSender_interToneGap - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCDtmfSender - * Method: registerObserver - * Signature: (Ldev/onvoid/webrtc/RTCDtmfSenderObserver;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDtmfSender_registerObserver - (JNIEnv *, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCDtmfSender - * Method: unregisterObserver - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDtmfSender_unregisterObserver - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/JNI_RTCPeerConnection.h b/webrtc-jni/src/main/cpp/include/JNI_RTCPeerConnection.h index 5ad409d..5b7fdec 100644 --- a/webrtc-jni/src/main/cpp/include/JNI_RTCPeerConnection.h +++ b/webrtc-jni/src/main/cpp/include/JNI_RTCPeerConnection.h @@ -7,53 +7,6 @@ #ifdef __cplusplus extern "C" { #endif - /* - * Class: dev_onvoid_webrtc_RTCPeerConnection - * Method: getSenders - * Signature: ()[Ldev/onvoid/webrtc/RTCRtpSender; - */ - JNIEXPORT jobjectArray JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getSenders - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCPeerConnection - * Method: getReceivers - * Signature: ()[Ldev/onvoid/webrtc/RTCRtpReceiver; - */ - JNIEXPORT jobjectArray JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getReceivers - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCPeerConnection - * Method: getTransceivers - * Signature: ()[Ldev/onvoid/webrtc/RTCRtpTransceiver; - */ - JNIEXPORT jobjectArray JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getTransceivers - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCPeerConnection - * Method: addTrack - * Signature: (Ldev/onvoid/webrtc/media/MediaStreamTrack;Ljava/util/List;)Ldev/onvoid/webrtc/RTCRtpSender; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_addTrack - (JNIEnv *, jobject, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCPeerConnection - * Method: removeTrack - * Signature: (Ldev/onvoid/webrtc/RTCRtpSender;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_removeTrack - (JNIEnv *, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCPeerConnection - * Method: addTransceiver - * Signature: (Ldev/onvoid/webrtc/media/MediaStreamTrack;Ldev/onvoid/webrtc/RTCRtpTransceiverInit;)Ldev/onvoid/webrtc/RTCRtpTransceiver; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_addTransceiver - (JNIEnv *, jobject, jobject, jobject); /* * Class: dev_onvoid_webrtc_RTCPeerConnection @@ -215,22 +168,6 @@ extern "C" { JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getStats__Ldev_onvoid_webrtc_RTCStatsCollectorCallback_2 (JNIEnv *, jobject, jobject); - /* - * Class: dev_onvoid_webrtc_RTCPeerConnection - * Method: getStats - * Signature: (Ldev/onvoid/webrtc/RTCRtpReceiver;Ldev/onvoid/webrtc/RTCStatsCollectorCallback;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getStats__Ldev_onvoid_webrtc_RTCRtpReceiver_2Ldev_onvoid_webrtc_RTCStatsCollectorCallback_2 - (JNIEnv *, jobject, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCPeerConnection - * Method: getStats - * Signature: (Ldev/onvoid/webrtc/RTCRtpSender;Ldev/onvoid/webrtc/RTCStatsCollectorCallback;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getStats__Ldev_onvoid_webrtc_RTCRtpSender_2Ldev_onvoid_webrtc_RTCStatsCollectorCallback_2 - (JNIEnv *, jobject, jobject, jobject); - /* * Class: dev_onvoid_webrtc_RTCPeerConnection * Method: restartIce diff --git a/webrtc-jni/src/main/cpp/include/JNI_RTCRtpReceiver.h b/webrtc-jni/src/main/cpp/include/JNI_RTCRtpReceiver.h deleted file mode 100644 index 3ff3658..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_RTCRtpReceiver.h +++ /dev/null @@ -1,53 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_RTCRtpReceiver */ - -#ifndef _Included_dev_onvoid_webrtc_RTCRtpReceiver -#define _Included_dev_onvoid_webrtc_RTCRtpReceiver -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_RTCRtpReceiver - * Method: getTrack - * Signature: ()Ldev/onvoid/webrtc/media/MediaStreamTrack; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpReceiver_getTrack - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCRtpReceiver - * Method: getTransport - * Signature: ()Ldev/onvoid/webrtc/RTCDtlsTransport; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpReceiver_getTransport - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCRtpReceiver - * Method: getParameters - * Signature: ()Ldev/onvoid/webrtc/RTCRtpParameters; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpReceiver_getParameters - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCRtpReceiver - * Method: getContributingSources - * Signature: ()Ljava/util/List; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpReceiver_getContributingSources - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCRtpReceiver - * Method: getSynchronizationSources - * Signature: ()Ljava/util/List; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpReceiver_getSynchronizationSources - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/webrtc-jni/src/main/cpp/include/JNI_RTCRtpSender.h b/webrtc-jni/src/main/cpp/include/JNI_RTCRtpSender.h deleted file mode 100644 index 83f23ff..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_RTCRtpSender.h +++ /dev/null @@ -1,69 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_RTCRtpSender */ - -#ifndef _Included_dev_onvoid_webrtc_RTCRtpSender -#define _Included_dev_onvoid_webrtc_RTCRtpSender -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_RTCRtpSender - * Method: getTrack - * Signature: ()Ldev/onvoid/webrtc/media/MediaStreamTrack; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpSender_getTrack - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCRtpSender - * Method: getTransport - * Signature: ()Ldev/onvoid/webrtc/RTCDtlsTransport; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpSender_getTransport - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCRtpSender - * Method: replaceTrack - * Signature: (Ldev/onvoid/webrtc/media/MediaStreamTrack;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCRtpSender_replaceTrack - (JNIEnv *, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCRtpSender - * Method: setParameters - * Signature: (Ldev/onvoid/webrtc/RTCRtpSendParameters;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCRtpSender_setParameters - (JNIEnv *, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCRtpSender - * Method: getParameters - * Signature: ()Ldev/onvoid/webrtc/RTCRtpSendParameters; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpSender_getParameters - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCRtpSender - * Method: setStreams - * Signature: (Ljava/util/List;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCRtpSender_setStreams - (JNIEnv *, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCRtpSender - * Method: getDtmfSender - * Signature: ()Ldev/onvoid/webrtc/RTCDtmfSender; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpSender_getDtmfSender - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/webrtc-jni/src/main/cpp/include/JNI_RTCRtpTransceiver.h b/webrtc-jni/src/main/cpp/include/JNI_RTCRtpTransceiver.h deleted file mode 100644 index d0b7419..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_RTCRtpTransceiver.h +++ /dev/null @@ -1,93 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_RTCRtpTransceiver */ - -#ifndef _Included_dev_onvoid_webrtc_RTCRtpTransceiver -#define _Included_dev_onvoid_webrtc_RTCRtpTransceiver -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_RTCRtpTransceiver - * Method: getMid - * Signature: ()Ljava/lang/String; - */ - JNIEXPORT jstring JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_getMid - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCRtpTransceiver - * Method: getSender - * Signature: ()Ldev/onvoid/webrtc/RTCRtpSender; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_getSender - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCRtpTransceiver - * Method: getReceiver - * Signature: ()Ldev/onvoid/webrtc/RTCRtpReceiver; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_getReceiver - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCRtpTransceiver - * Method: getDirection - * Signature: ()Ldev/onvoid/webrtc/RTCRtpTransceiverDirection; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_getDirection - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCRtpTransceiver - * Method: setDirection - * Signature: (Ldev/onvoid/webrtc/RTCRtpTransceiverDirection;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_setDirection - (JNIEnv *, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCRtpTransceiver - * Method: getCurrentDirection - * Signature: ()Ldev/onvoid/webrtc/RTCRtpTransceiverDirection; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_getCurrentDirection - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCRtpTransceiver - * Method: stop - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_stop - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCRtpTransceiver - * Method: stopped - * Signature: ()Z - */ - JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_stopped - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCRtpTransceiver - * Method: getCodecPreferences - * Signature: ()Ljava/util/List; - */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_getCodecPreferences - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_RTCRtpTransceiver - * Method: setCodecPreferences - * Signature: (Ljava/util/List;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_setCodecPreferences - (JNIEnv *, jobject, jobject); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/webrtc-jni/src/main/cpp/include/JNI_ScreenCapturer.h b/webrtc-jni/src/main/cpp/include/JNI_ScreenCapturer.h deleted file mode 100644 index ccb0af3..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_ScreenCapturer.h +++ /dev/null @@ -1,21 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_media_video_desktop_ScreenCapturer */ - -#ifndef _Included_dev_onvoid_webrtc_media_video_desktop_ScreenCapturer -#define _Included_dev_onvoid_webrtc_media_video_desktop_ScreenCapturer -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_media_video_desktop_ScreenCapturer - * Method: initialize - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_desktop_ScreenCapturer_initialize - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/webrtc-jni/src/main/cpp/include/JNI_SyncClock.h b/webrtc-jni/src/main/cpp/include/JNI_SyncClock.h deleted file mode 100644 index 04a62b4..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_SyncClock.h +++ /dev/null @@ -1,53 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_media_SyncClock */ - -#ifndef _Included_dev_onvoid_webrtc_media_SyncClock -#define _Included_dev_onvoid_webrtc_media_SyncClock -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_media_SyncClock - * Method: getTimestampUs - * Signature: ()J - */ - JNIEXPORT jlong JNICALL Java_dev_onvoid_webrtc_media_SyncClock_getTimestampUs - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_SyncClock - * Method: getTimestampMs - * Signature: ()J - */ - JNIEXPORT jlong JNICALL Java_dev_onvoid_webrtc_media_SyncClock_getTimestampMs - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_SyncClock - * Method: getNtpTime - * Signature: ()J - */ - JNIEXPORT jlong JNICALL Java_dev_onvoid_webrtc_media_SyncClock_getNtpTime - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_SyncClock - * Method: dispose - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_SyncClock_dispose - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_SyncClock - * Method: initialize - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_SyncClock_initialize - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/JNI_VideoBufferConverter.h b/webrtc-jni/src/main/cpp/include/JNI_VideoBufferConverter.h deleted file mode 100644 index 8373597..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_VideoBufferConverter.h +++ /dev/null @@ -1,45 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_media_video_VideoBufferConverter */ - -#ifndef _Included_dev_onvoid_webrtc_media_video_VideoBufferConverter -#define _Included_dev_onvoid_webrtc_media_video_VideoBufferConverter -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_media_video_VideoBufferConverter - * Method: I420toByteArray - * Signature: (Ljava/nio/ByteBuffer;ILjava/nio/ByteBuffer;ILjava/nio/ByteBuffer;I[BIII)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoBufferConverter_I420toByteArray - (JNIEnv *, jclass, jobject, jint, jobject, jint, jobject, jint, jbyteArray, jint, jint, jint); - - /* - * Class: dev_onvoid_webrtc_media_video_VideoBufferConverter - * Method: I420toDirectBuffer - * Signature: (Ljava/nio/ByteBuffer;ILjava/nio/ByteBuffer;ILjava/nio/ByteBuffer;ILjava/nio/ByteBuffer;III)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoBufferConverter_I420toDirectBuffer - (JNIEnv *, jclass, jobject, jint, jobject, jint, jobject, jint, jobject, jint, jint, jint); - - /* - * Class: dev_onvoid_webrtc_media_video_VideoBufferConverter - * Method: byteArrayToI420 - * Signature: ([BIILjava/nio/ByteBuffer;ILjava/nio/ByteBuffer;ILjava/nio/ByteBuffer;II)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoBufferConverter_byteArrayToI420 - (JNIEnv *, jclass, jbyteArray, jint, jint, jobject, jint, jobject, jint, jobject, jint, jint); - - /* - * Class: dev_onvoid_webrtc_media_video_VideoBufferConverter - * Method: directBufferToI420 - * Signature: (Ljava/nio/ByteBuffer;IILjava/nio/ByteBuffer;ILjava/nio/ByteBuffer;ILjava/nio/ByteBuffer;II)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoBufferConverter_directBufferToI420 - (JNIEnv *, jclass, jobject, jint, jint, jobject, jint, jobject, jint, jobject, jint, jint); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/webrtc-jni/src/main/cpp/include/JNI_VideoCapture.h b/webrtc-jni/src/main/cpp/include/JNI_VideoCapture.h deleted file mode 100644 index 8371bc7..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_VideoCapture.h +++ /dev/null @@ -1,69 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_media_video_VideoCapture */ - -#ifndef _Included_dev_onvoid_webrtc_media_video_VideoCapture -#define _Included_dev_onvoid_webrtc_media_video_VideoCapture -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_media_video_VideoCapture - * Method: setVideoCaptureDevice - * Signature: (Ldev/onvoid/webrtc/media/video/VideoDevice;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoCapture_setVideoCaptureDevice - (JNIEnv *, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_media_video_VideoCapture - * Method: setVideoCaptureCapability - * Signature: (Ldev/onvoid/webrtc/media/video/VideoCaptureCapability;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoCapture_setVideoCaptureCapability - (JNIEnv *, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_media_video_VideoCapture - * Method: setVideoSink - * Signature: (Ldev/onvoid/webrtc/media/video/VideoTrackSink;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoCapture_setVideoSink - (JNIEnv *, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_media_video_VideoCapture - * Method: start - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoCapture_start - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_video_VideoCapture - * Method: stop - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoCapture_stop - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_video_VideoCapture - * Method: dispose - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoCapture_dispose - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_video_VideoCapture - * Method: initialize - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoCapture_initialize - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/webrtc-jni/src/main/cpp/include/JNI_VideoDesktopSource.h b/webrtc-jni/src/main/cpp/include/JNI_VideoDesktopSource.h deleted file mode 100644 index b255b3e..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_VideoDesktopSource.h +++ /dev/null @@ -1,77 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_media_video_VideoDesktopSource */ - -#ifndef _Included_dev_onvoid_webrtc_media_video_VideoDesktopSource -#define _Included_dev_onvoid_webrtc_media_video_VideoDesktopSource -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_media_video_VideoDesktopSource - * Method: setSourceId - * Signature: (JZ)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDesktopSource_setSourceId - (JNIEnv*, jobject, jlong, jboolean); - - /* - * Class: dev_onvoid_webrtc_media_video_VideoDesktopSource - * Method: setFrameRate - * Signature: (I)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDesktopSource_setFrameRate - (JNIEnv*, jobject, jint); - - /* - * Class: dev_onvoid_webrtc_media_video_VideoDesktopSource - * Method: setMaxFrameSize - * Signature: (II)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDesktopSource_setMaxFrameSize - (JNIEnv*, jobject, jint, jint); - - /* - * Class: dev_onvoid_webrtc_media_video_VideoDesktopSource - * Method: setFocusSelectedSource - * Signature: (Z)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDesktopSource_setFocusSelectedSource - (JNIEnv*, jobject, jboolean); - - /* - * Class: dev_onvoid_webrtc_media_video_VideoDesktopSource - * Method: start - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDesktopSource_start - (JNIEnv*, jobject); - - /* - * Class: dev_onvoid_webrtc_media_video_VideoDesktopSource - * Method: stop - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDesktopSource_stop - (JNIEnv*, jobject); - - /* - * Class: dev_onvoid_webrtc_media_video_VideoDesktopSource - * Method: dispose - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDesktopSource_dispose - (JNIEnv*, jobject); - - /* - * Class: dev_onvoid_webrtc_media_video_VideoDesktopSource - * Method: initialize - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDesktopSource_initialize - (JNIEnv*, jobject); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/webrtc-jni/src/main/cpp/include/JNI_VideoDeviceSource.h b/webrtc-jni/src/main/cpp/include/JNI_VideoDeviceSource.h deleted file mode 100644 index 3c1b300..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_VideoDeviceSource.h +++ /dev/null @@ -1,61 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_media_video_VideoDeviceSource */ - -#ifndef _Included_dev_onvoid_webrtc_media_video_VideoDeviceSource -#define _Included_dev_onvoid_webrtc_media_video_VideoDeviceSource -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_media_video_VideoDeviceSource - * Method: setVideoCaptureDevice - * Signature: (Ldev/onvoid/webrtc/media/video/VideoDevice;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDeviceSource_setVideoCaptureDevice - (JNIEnv *, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_media_video_VideoDeviceSource - * Method: setVideoCaptureCapability - * Signature: (Ldev/onvoid/webrtc/media/video/VideoCaptureCapability;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDeviceSource_setVideoCaptureCapability - (JNIEnv *, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_media_video_VideoDeviceSource - * Method: start - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDeviceSource_start - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_video_VideoDeviceSource - * Method: stop - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDeviceSource_stop - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_video_VideoDeviceSource - * Method: dispose - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDeviceSource_dispose - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_video_VideoDeviceSource - * Method: initialize - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDeviceSource_initialize - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/webrtc-jni/src/main/cpp/include/JNI_VideoTrack.h b/webrtc-jni/src/main/cpp/include/JNI_VideoTrack.h deleted file mode 100644 index 5333b3d..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_VideoTrack.h +++ /dev/null @@ -1,29 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_media_video_VideoTrack */ - -#ifndef _Included_dev_onvoid_webrtc_media_video_VideoTrack -#define _Included_dev_onvoid_webrtc_media_video_VideoTrack -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_media_video_VideoTrack - * Method: addSinkInternal - * Signature: (Ldev/onvoid/webrtc/media/video/VideoTrackSink;)J - */ - JNIEXPORT jlong JNICALL Java_dev_onvoid_webrtc_media_video_VideoTrack_addSinkInternal - (JNIEnv *, jobject, jobject); - - /* - * Class: dev_onvoid_webrtc_media_video_VideoTrack - * Method: removeSinkInternal - * Signature: (J)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoTrack_removeSinkInternal - (JNIEnv *, jobject, jlong); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/webrtc-jni/src/main/cpp/include/JNI_VoiceActivityDetector.h b/webrtc-jni/src/main/cpp/include/JNI_VoiceActivityDetector.h deleted file mode 100644 index ccda4dd..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_VoiceActivityDetector.h +++ /dev/null @@ -1,45 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_media_audio_VoiceActivityDetector */ - -#ifndef _Included_dev_onvoid_webrtc_media_audio_VoiceActivityDetector -#define _Included_dev_onvoid_webrtc_media_audio_VoiceActivityDetector -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_media_audio_VoiceActivityDetector - * Method: process - * Signature: ([BII)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_VoiceActivityDetector_process - (JNIEnv *, jobject, jbyteArray, jint, jint); - - /* - * Class: dev_onvoid_webrtc_media_audio_VoiceActivityDetector - * Method: getLastVoiceProbability - * Signature: ()F - */ - JNIEXPORT jfloat JNICALL Java_dev_onvoid_webrtc_media_audio_VoiceActivityDetector_getLastVoiceProbability - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_VoiceActivityDetector - * Method: dispose - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_VoiceActivityDetector_dispose - (JNIEnv *, jobject); - - /* - * Class: dev_onvoid_webrtc_media_audio_VoiceActivityDetector - * Method: initialize - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_VoiceActivityDetector_initialize - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/JNI_WebRTC.h b/webrtc-jni/src/main/cpp/include/JNI_WebRTC.h index 0eb3888..26405d1 100644 --- a/webrtc-jni/src/main/cpp/include/JNI_WebRTC.h +++ b/webrtc-jni/src/main/cpp/include/JNI_WebRTC.h @@ -20,10 +20,6 @@ #define PKG "dev/onvoid/webrtc/" #define PKG_INTERNAL "dev/onvoid/webrtc/internal/" #define PKG_LOG "dev/onvoid/webrtc/logging/" -#define PKG_MEDIA "dev/onvoid/webrtc/media/" -#define PKG_AUDIO "dev/onvoid/webrtc/media/audio/" -#define PKG_VIDEO "dev/onvoid/webrtc/media/video/" -#define PKG_DESKTOP "dev/onvoid/webrtc/media/video/desktop/" #define BOOLEAN_SIG "Ljava/lang/Boolean;" #define DOUBLE_SIG "Ljava/lang/Double;" diff --git a/webrtc-jni/src/main/cpp/include/JNI_WindowCapturer.h b/webrtc-jni/src/main/cpp/include/JNI_WindowCapturer.h deleted file mode 100644 index ed7bdda..0000000 --- a/webrtc-jni/src/main/cpp/include/JNI_WindowCapturer.h +++ /dev/null @@ -1,21 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class dev_onvoid_webrtc_media_video_desktop_WindowCapturer */ - -#ifndef _Included_dev_onvoid_webrtc_media_video_desktop_WindowCapturer -#define _Included_dev_onvoid_webrtc_media_video_desktop_WindowCapturer -#ifdef __cplusplus -extern "C" { -#endif - /* - * Class: dev_onvoid_webrtc_media_video_desktop_WindowCapturer - * Method: initialize - * Signature: ()V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_desktop_WindowCapturer_initialize - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/webrtc-jni/src/main/cpp/include/WebRTCContext.h b/webrtc-jni/src/main/cpp/include/WebRTCContext.h index 9b7d405..03a78d9 100644 --- a/webrtc-jni/src/main/cpp/include/WebRTCContext.h +++ b/webrtc-jni/src/main/cpp/include/WebRTCContext.h @@ -19,45 +19,24 @@ #include "JavaContext.h" #include "api/environment/environment.h" -#include "media/audio/AudioDeviceManager.h" -#include "media/video/VideoDeviceManager.h" -#include "media/video/desktop/PowerManagement.h" #include #include -#include namespace jni { - class WebRTCContext : public JavaContext - { - public: - WebRTCContext(JavaVM * vm); - ~WebRTCContext() = default; - - void initialize(JNIEnv * env) override; - void initializeClassLoader(JNIEnv* env, const char * loaderName) override; - void destroy(JNIEnv * env) override; - - avdev::AudioDeviceManager * getAudioDeviceManager(); - avdev::VideoDeviceManager * getVideoDeviceManager(); - avdev::PowerManagement * getPowerManagement(); - - const webrtc::Environment webrtcEnv; - - private: - void initializeAudioManager(); - void initializeVideoManager(); - void initializePowerManagement(); - - private: - std::mutex aMutex; - std::mutex vMutex; - std::unique_ptr audioDevManager; - std::unique_ptr videoDevManager; - std::unique_ptr powerManagement; - }; + class WebRTCContext : public JavaContext + { + public: + WebRTCContext(JavaVM * vm); + ~WebRTCContext() = default; + + void initialize(JNIEnv * env) override; + void initializeClassLoader(JNIEnv* env, const char * loaderName) override; + void destroy(JNIEnv * env) override; + + const webrtc::Environment webrtcEnv; + }; } #endif - diff --git a/webrtc-jni/src/main/cpp/include/api/AudioOptions.h b/webrtc-jni/src/main/cpp/include/api/AudioOptions.h deleted file mode 100644 index 1c5e645..0000000 --- a/webrtc-jni/src/main/cpp/include/api/AudioOptions.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_API_AUDIO_OPTIONS_H_ -#define JNI_WEBRTC_API_AUDIO_OPTIONS_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include "api/audio_options.h" - -#include - -namespace jni -{ - namespace AudioOptions - { - class JavaAudioOptionsClass : public JavaClass - { - public: - explicit JavaAudioOptionsClass(JNIEnv * env); - - jclass cls; - jfieldID echoCancellation; - jfieldID autoGainControl; - jfieldID noiseSuppression; - jfieldID highpassFilter; - jfieldID typingDetection; - jfieldID residualEchoDetector; - }; - - webrtc::AudioOptions toNative(JNIEnv * env, const JavaRef & javaType); - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/api/AudioTrackSink.h b/webrtc-jni/src/main/cpp/include/api/AudioTrackSink.h deleted file mode 100644 index fc65fe9..0000000 --- a/webrtc-jni/src/main/cpp/include/api/AudioTrackSink.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_API_AUDIO_TRACK_SINK_H_ -#define JNI_WEBRTC_API_AUDIO_TRACK_SINK_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include "api/media_stream_interface.h" - -#include - -namespace jni -{ - class AudioTrackSink : public webrtc::AudioTrackSinkInterface - { - public: - AudioTrackSink(JNIEnv * env, const JavaGlobalRef & sink); - ~AudioTrackSink() = default; - - // AudioTrackSinkInterface implementation. - void OnData(const void * data, int bitsPerSample, int sampleRate, size_t channels, size_t frames) override; - - private: - class JavaAudioTrackSinkClass : public JavaClass - { - public: - explicit JavaAudioTrackSinkClass(JNIEnv * env); - - jmethodID onData; - }; - - private: - JavaGlobalRef sink; - - const std::shared_ptr javaClass; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/api/HeadlessAudioDeviceModule.h b/webrtc-jni/src/main/cpp/include/api/HeadlessAudioDeviceModule.h deleted file mode 100644 index c3ae3c3..0000000 --- a/webrtc-jni/src/main/cpp/include/api/HeadlessAudioDeviceModule.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_API_HEADLESS_ADM_H_ -#define JNI_WEBRTC_API_HEADLESS_ADM_H_ - -#include -#include -#include -#include -#include - -#include "api/environment/environment.h" -#include "api/environment/environment_factory.h" -#include "api/make_ref_counted.h" -#include "modules/audio_device/audio_device_buffer.h" -#include "modules/audio_device/include/audio_device.h" -#include "modules/audio_device/include/audio_device_defines.h" -#include "rtc_base/buffer.h" -#include "rtc_base/platform_thread.h" -#include "rtc_base/ref_counted_object.h" -#include "rtc_base/synchronization/mutex.h" -#include "rtc_base/thread.h" -#include "rtc_base/time_utils.h" - -namespace jni -{ - // A headless AudioDeviceModule that drives the render pipeline by pulling - // 10 ms PCM chunks from AudioTransport and discarding them, and simulates - // a microphone by pulling 10 ms PCM chunks from the registered AudioTransport - // and feeding them into the WebRTC capture pipeline. - class HeadlessAudioDeviceModule : public webrtc::AudioDeviceModule - { - public: - static webrtc::scoped_refptr Create( - const webrtc::Environment & env, - int sample_rate_hz = 48000, - size_t channels = 1) - { - return webrtc::make_ref_counted( - env, sample_rate_hz, channels); - } - - HeadlessAudioDeviceModule(const webrtc::Environment & env, int sample_rate_hz, size_t channels); - ~HeadlessAudioDeviceModule() override; - - // ----- AudioDeviceModule interface ----- - int32_t ActiveAudioLayer(webrtc::AudioDeviceModule::AudioLayer * audioLayer) const override; - int32_t RegisterAudioCallback(webrtc::AudioTransport * audioCallback) override; - int32_t Init() override; - int32_t Terminate() override; - bool Initialized() const override; - - // --- Device enumeration (stubbed; 1 virtual output device) --- - int16_t PlayoutDevices() override; - int16_t RecordingDevices() override; - int32_t PlayoutDeviceName(uint16_t index, - char name[webrtc::kAdmMaxDeviceNameSize], - char guid[webrtc::kAdmMaxGuidSize]) override; - int32_t RecordingDeviceName(uint16_t index, - char name[webrtc::kAdmMaxDeviceNameSize], - char guid[webrtc::kAdmMaxGuidSize]) override; - - // --- Device selection (recording not supported) --- - int32_t SetPlayoutDevice(uint16_t index) override; - int32_t SetPlayoutDevice(WindowsDeviceType device) override; - int32_t SetRecordingDevice(uint16_t index) override; - int32_t SetRecordingDevice(WindowsDeviceType device) override; - - // --- Audio transport initialization --- - int32_t PlayoutIsAvailable(bool * available) override; - int32_t InitPlayout() override; - bool PlayoutIsInitialized() const override; - int32_t RecordingIsAvailable(bool * available) override; - int32_t InitRecording() override; - bool RecordingIsInitialized() const override; - - // --- Audio transport control (playout only) --- - int32_t StartPlayout() override; - int32_t StopPlayout() override; - bool Playing() const override; - int32_t StartRecording() override; - int32_t StopRecording() override; - bool Recording() const override; - - // --- Mixer init (report success; nothing to init physically) --- - int32_t InitSpeaker() override; - bool SpeakerIsInitialized() const override; - int32_t InitMicrophone() override; - bool MicrophoneIsInitialized() const override; - - // --- Speaker volume (not supported) --- - int32_t SpeakerVolumeIsAvailable(bool * available) override; - int32_t SetSpeakerVolume(uint32_t volume) override; - int32_t SpeakerVolume(uint32_t * volume) const override; - int32_t MaxSpeakerVolume(uint32_t * maxVolume) const override; - int32_t MinSpeakerVolume(uint32_t * minVolume) const override; - - // --- Microphone volume (not supported) --- - int32_t MicrophoneVolumeIsAvailable(bool * available) override; - int32_t SetMicrophoneVolume(uint32_t volume) override; - int32_t MicrophoneVolume(uint32_t * volume) const override; - int32_t MaxMicrophoneVolume(uint32_t * maxVolume) const override; - int32_t MinMicrophoneVolume(uint32_t * minVolume) const override; - - // --- Mute controls (not supported) --- - int32_t SpeakerMuteIsAvailable(bool * available) override; - int32_t SetSpeakerMute(bool enable) override; - int32_t SpeakerMute(bool * enabled) const override; - int32_t MicrophoneMuteIsAvailable(bool * available) override; - int32_t SetMicrophoneMute(bool enable) override; - int32_t MicrophoneMute(bool * enabled) const override; - - // --- Stereo support (playout only) --- - int32_t StereoPlayoutIsAvailable(bool * available) const override; - int32_t SetStereoPlayout(bool enable) override; - int32_t StereoPlayout(bool * enabled) const override; - int32_t StereoRecordingIsAvailable(bool * available) const override; - int32_t SetStereoRecording(bool enable) override; - int32_t StereoRecording(bool * enabled) const override; - - // --- Playout delay (fixed, nominal) --- - int32_t PlayoutDelay(uint16_t * delayMS) const override; - - // --- Built-in effects (not supported here) --- - bool BuiltInAECIsAvailable() const override; - bool BuiltInAGCIsAvailable() const override; - bool BuiltInNSIsAvailable() const override; - int32_t EnableBuiltInAEC(bool enable) override; - int32_t EnableBuiltInAGC(bool enable) override; - int32_t EnableBuiltInNS(bool enable) override; - - // Android-only in real ADMs; just return 0 here. - int32_t GetPlayoutUnderrunCount() const override; - - private: - bool PlayThreadProcess(); - bool CaptureThreadProcess(); - - // State - bool initialized_ = false; - bool playout_initialized_ = false; - bool recording_initialized_ = false; - bool playing_ = false; - bool recording_ = false; - - // Format - int sample_rate_hz_ = 48000; - size_t channels_ = 1; - - webrtc::BufferT play_buffer_; - webrtc::BufferT record_buffer_; - - size_t playoutFramesIn10MS_; - size_t recordingFramesIn10MS_; - int64_t lastCallPlayoutMillis_; - int64_t lastCallRecordMillis_; - - mutable webrtc::Mutex mutex_; - std::unique_ptr audio_device_buffer_ RTC_GUARDED_BY(mutex_); - webrtc::AudioTransport * audio_callback_; - - webrtc::PlatformThread render_thread_; - webrtc::PlatformThread capture_thread_; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/api/PeerConnectionObserver.h b/webrtc-jni/src/main/cpp/include/api/PeerConnectionObserver.h index 55b5ef9..3f2f0d2 100644 --- a/webrtc-jni/src/main/cpp/include/api/PeerConnectionObserver.h +++ b/webrtc-jni/src/main/cpp/include/api/PeerConnectionObserver.h @@ -36,9 +36,6 @@ namespace jni // PeerConnectionObserver implementation. void OnConnectionChange(webrtc::PeerConnectionInterface::PeerConnectionState state) override; void OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState state) override; - void OnTrack(webrtc::scoped_refptr transceiver) override; - void OnAddTrack(webrtc::scoped_refptr receiver, const std::vector> & streams) override; - void OnRemoveTrack(webrtc::scoped_refptr receiver) override; void OnDataChannel(webrtc::scoped_refptr channel) override; void OnRenegotiationNeeded() override; void OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState state) override; @@ -56,9 +53,6 @@ namespace jni jmethodID onConnectionChange; jmethodID onSignalingChange; - jmethodID onTrack; - jmethodID onAddTrack; - jmethodID onRemoveTrack; jmethodID onDataChannel; jmethodID onRenegotiationNeeded; jmethodID onIceConnectionChange; diff --git a/webrtc-jni/src/main/cpp/include/api/RTCDtmfSender.h b/webrtc-jni/src/main/cpp/include/api/RTCDtmfSender.h deleted file mode 100644 index 98cf6a2..0000000 --- a/webrtc-jni/src/main/cpp/include/api/RTCDtmfSender.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_API_RTC_DTMF_SENDER_H_ -#define JNI_WEBRTC_API_RTC_DTMF_SENDER_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include "api/dtmf_sender_interface.h" - -#include - -namespace jni -{ - namespace RTCDtmfSender - { - class JavaRTCDtmfSenderClass : public JavaClass - { - public: - explicit JavaRTCDtmfSenderClass(JNIEnv * env); - - jclass cls; - jmethodID ctor; - }; - - JavaLocalRef toJava(JNIEnv * env); - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/api/RTCDtmfSenderObserver.h b/webrtc-jni/src/main/cpp/include/api/RTCDtmfSenderObserver.h deleted file mode 100644 index 994ea04..0000000 --- a/webrtc-jni/src/main/cpp/include/api/RTCDtmfSenderObserver.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_API_RTC_DTMF_SENDER_OBSERVER_H_ -#define JNI_WEBRTC_API_RTC_DTMF_SENDER_OBSERVER_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include "api/dtmf_sender_interface.h" - -#include -#include - -namespace jni -{ - class RTCDtmfSenderObserver : public webrtc::DtmfSenderObserverInterface - { - public: - explicit RTCDtmfSenderObserver(JNIEnv * env, const JavaGlobalRef & observer); - ~RTCDtmfSenderObserver() = default; - - // DtmfSenderObserverInterface implementation. - void OnToneChange(const std::string & tone, const std::string & tone_buffer) override; - - private: - class JavaRTCDtmfSenderObserverClass : public JavaClass - { - public: - explicit JavaRTCDtmfSenderObserverClass(JNIEnv * env); - - jmethodID onToneChange; - }; - - private: - JavaGlobalRef observer; - - const std::shared_ptr javaClass; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/api/RTCRtcpParameters.h b/webrtc-jni/src/main/cpp/include/api/RTCRtcpParameters.h deleted file mode 100644 index 598c3ec..0000000 --- a/webrtc-jni/src/main/cpp/include/api/RTCRtcpParameters.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_API_RTC_RTCP_PARAMETERS_H_ -#define JNI_WEBRTC_API_RTC_RTCP_PARAMETERS_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include "api/rtp_parameters.h" - -#include - -namespace jni -{ - namespace RTCRtcpParameters - { - class JavaRTCRtcpParametersClass : public JavaClass - { - public: - explicit JavaRTCRtcpParametersClass(JNIEnv * env); - - jclass cls; - jmethodID ctor; - jfieldID cName; - jfieldID reducedSize; - }; - - JavaLocalRef toJava(JNIEnv * env, const webrtc::RtcpParameters & parameters); - webrtc::RtcpParameters toNative(JNIEnv * env, const JavaRef & parameters); - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/api/RTCRtpCapabilities.h b/webrtc-jni/src/main/cpp/include/api/RTCRtpCapabilities.h deleted file mode 100644 index 437a15f..0000000 --- a/webrtc-jni/src/main/cpp/include/api/RTCRtpCapabilities.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_API_RTC_RTP_CAPABILITIES_H_ -#define JNI_WEBRTC_API_RTC_RTP_CAPABILITIES_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include "api/rtp_parameters.h" - -#include - -namespace jni -{ - namespace RTCRtpCapabilities - { - class JavaRTCRtpCapabilitiesClass : public JavaClass - { - public: - explicit JavaRTCRtpCapabilitiesClass(JNIEnv * env); - - jclass cls; - jmethodID ctor; - }; - - JavaLocalRef toJava(JNIEnv * env, const webrtc::RtpCapabilities & capabilities); - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/api/RTCRtpCodecCapability.h b/webrtc-jni/src/main/cpp/include/api/RTCRtpCodecCapability.h deleted file mode 100644 index 7a8dc62..0000000 --- a/webrtc-jni/src/main/cpp/include/api/RTCRtpCodecCapability.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_API_RTC_RTP_CODEC_CAPABILITY_H_ -#define JNI_WEBRTC_API_RTC_RTP_CODEC_CAPABILITY_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include "api/rtp_parameters.h" - -#include - -namespace jni -{ - namespace RTCRtpCodecCapability - { - class JavaRTCRtpCodecCapabilityClass : public JavaClass - { - public: - explicit JavaRTCRtpCodecCapabilityClass(JNIEnv * env); - - jclass cls; - jmethodID ctor; - jfieldID mediaType; - jfieldID name; - jfieldID clockRate; - jfieldID channels; - jfieldID sdpFmtp; - }; - - JavaLocalRef toJava(JNIEnv * env, const webrtc::RtpCodecCapability & capability); - webrtc::RtpCodecCapability toNative(JNIEnv * env, const JavaRef & capability); - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/api/RTCRtpCodecParameters.h b/webrtc-jni/src/main/cpp/include/api/RTCRtpCodecParameters.h deleted file mode 100644 index 3503c61..0000000 --- a/webrtc-jni/src/main/cpp/include/api/RTCRtpCodecParameters.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_API_RTC_RTP_CODEC_PARAMETERS_H_ -#define JNI_WEBRTC_API_RTC_RTP_CODEC_PARAMETERS_H_ - -#include "JavaClass.h" -#include "JavaObject.h" - -#include "api/rtp_parameters.h" - -#include - -namespace jni -{ - namespace RTCRtpCodecParameters - { - class JavaRTCRtpCodecParametersClass : public JavaClass - { - public: - explicit JavaRTCRtpCodecParametersClass(JNIEnv * env); - - jclass cls; - jmethodID ctor; - jfieldID payloadType; - jfieldID mediaType; - jfieldID codecName; - jfieldID clockRate; - jfieldID channels; - jfieldID parameters; - }; - - JavaLocalRef toJava(JNIEnv * env, const webrtc::RtpCodecParameters & parameters); - webrtc::RtpCodecParameters toNative(JNIEnv * env, const JavaRef & parameters); - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/api/RTCRtpContributingSource.h b/webrtc-jni/src/main/cpp/include/api/RTCRtpContributingSource.h deleted file mode 100644 index 07cccd8..0000000 --- a/webrtc-jni/src/main/cpp/include/api/RTCRtpContributingSource.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_API_RTC_RTP_CONTRIBUTING_SOURCE_H_ -#define JNI_WEBRTC_API_RTC_RTP_CONTRIBUTING_SOURCE_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include "api/transport/rtp/rtp_source.h" - -#include - -namespace jni -{ - namespace RTCRtpContributingSource - { - class JavaRTCRtpContributingSourceClass : public JavaClass - { - public: - explicit JavaRTCRtpContributingSourceClass(JNIEnv * env); - - jclass cls; - jmethodID ctor; - jfieldID timestamp; - jfieldID sourceId; - jfieldID sourceType; - jfieldID audioLevel; - jfieldID rtpTimestamp; - }; - - JavaLocalRef toJava(JNIEnv * env, const webrtc::RtpSource & source); - webrtc::RtpSource toNative(JNIEnv * env, const JavaRef & source); - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/api/RTCRtpEncodingParameters.h b/webrtc-jni/src/main/cpp/include/api/RTCRtpEncodingParameters.h deleted file mode 100644 index 6e2c4d4..0000000 --- a/webrtc-jni/src/main/cpp/include/api/RTCRtpEncodingParameters.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_API_RTC_RTP_ENCODING_PARAMETERS_H_ -#define JNI_WEBRTC_API_RTC_RTP_ENCODING_PARAMETERS_H_ - -#include "JavaClass.h" -#include "JavaObject.h" - -#include "api/rtp_parameters.h" - -#include - -namespace jni -{ - namespace RTCRtpEncodingParameters - { - class JavaRTCRtpEncodingParametersClass : public JavaClass - { - public: - explicit JavaRTCRtpEncodingParametersClass(JNIEnv * env); - - jclass cls; - jmethodID ctor; - jfieldID ssrc; - jfieldID active; - jfieldID minBitrate; - jfieldID maxBitrate; - jfieldID maxFramerate; - jfieldID scaleResolution; - }; - - JavaLocalRef toJava(JNIEnv * env, const webrtc::RtpEncodingParameters & parameters); - webrtc::RtpEncodingParameters toNative(JNIEnv * env, const JavaRef & parameters); - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/api/RTCRtpHeaderExtension.h b/webrtc-jni/src/main/cpp/include/api/RTCRtpHeaderExtension.h deleted file mode 100644 index a45d4df..0000000 --- a/webrtc-jni/src/main/cpp/include/api/RTCRtpHeaderExtension.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_API_RTC_RTP_HEADER_EXTENSION_H_ -#define JNI_WEBRTC_API_RTC_RTP_HEADER_EXTENSION_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include "api/rtp_parameters.h" - -#include - -namespace jni -{ - namespace RTCRtpHeaderExtension - { - class JavaRTCRtpHeaderExtensionClass : public JavaClass - { - public: - explicit JavaRTCRtpHeaderExtensionClass(JNIEnv * env); - - jclass cls; - jmethodID ctor; - jfieldID uri; - jfieldID id; - jfieldID encrypted; - }; - - JavaLocalRef toJava(JNIEnv * env, const webrtc::RtpExtension & extension); - webrtc::RtpExtension toNative(JNIEnv * env, const JavaRef & jExtension); - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/api/RTCRtpHeaderExtensionCapability.h b/webrtc-jni/src/main/cpp/include/api/RTCRtpHeaderExtensionCapability.h deleted file mode 100644 index cd7c68f..0000000 --- a/webrtc-jni/src/main/cpp/include/api/RTCRtpHeaderExtensionCapability.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_API_RTC_RTP_HEADER_EXT_CAPABILITY_H_ -#define JNI_WEBRTC_API_RTC_RTP_HEADER_EXT_CAPABILITY_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include "api/rtp_parameters.h" - -#include - -namespace jni -{ - namespace RTCRtpHeaderExtensionCapability - { - class JavaRTCRtpHeaderExtensionCapabilityClass : public JavaClass - { - public: - explicit JavaRTCRtpHeaderExtensionCapabilityClass(JNIEnv * env); - - jclass cls; - jmethodID ctor; - }; - - JavaLocalRef toJava(JNIEnv * env, const webrtc::RtpHeaderExtensionCapability & capability); - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/api/RTCRtpParameters.h b/webrtc-jni/src/main/cpp/include/api/RTCRtpParameters.h deleted file mode 100644 index b1cb155..0000000 --- a/webrtc-jni/src/main/cpp/include/api/RTCRtpParameters.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_API_RTC_RTP_PARAMETERS_H_ -#define JNI_WEBRTC_API_RTC_RTP_PARAMETERS_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include "api/rtp_parameters.h" - -#include - -namespace jni -{ - namespace RTCRtpParameters - { - class JavaRTCRtpParametersClass : public JavaClass - { - public: - explicit JavaRTCRtpParametersClass(JNIEnv * env); - - jclass cls; - jmethodID ctor; - jfieldID headerExtensions; - jfieldID rtcp; - jfieldID codecs; - }; - - JavaLocalRef toJava(JNIEnv * env, const webrtc::RtpParameters & parameters); - webrtc::RtpParameters toNative(JNIEnv * env, const JavaRef & parameters); - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/api/RTCRtpSendParameters.h b/webrtc-jni/src/main/cpp/include/api/RTCRtpSendParameters.h deleted file mode 100644 index 61ab494..0000000 --- a/webrtc-jni/src/main/cpp/include/api/RTCRtpSendParameters.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_API_RTC_RTP_SEND_PARAMETERS_H_ -#define JNI_WEBRTC_API_RTC_RTP_SEND_PARAMETERS_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include "api/rtp_parameters.h" - -#include - -namespace jni -{ - namespace RTCRtpSendParameters - { - class JavaRTCRtpSendParametersClass : public JavaClass - { - public: - explicit JavaRTCRtpSendParametersClass(JNIEnv * env); - - jclass cls; - jmethodID ctor; - jfieldID transactionId; - jfieldID encodings; - }; - - JavaLocalRef toJava(JNIEnv * env, const webrtc::RtpParameters & parameters); - webrtc::RtpParameters toNative(JNIEnv * env, const JavaRef & parameters); - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/api/RTCRtpSynchronizationSource.h b/webrtc-jni/src/main/cpp/include/api/RTCRtpSynchronizationSource.h deleted file mode 100644 index 760d4b4..0000000 --- a/webrtc-jni/src/main/cpp/include/api/RTCRtpSynchronizationSource.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_API_RTC_RTP_SYNCHRONIZATION_SOURCE_H_ -#define JNI_WEBRTC_API_RTC_RTP_SYNCHRONIZATION_SOURCE_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include "api/transport/rtp/rtp_source.h" - -#include - -namespace jni -{ - namespace RTCRtpSynchronizationSource - { - class JavaRTCRtpSynchronizationSourceClass : public JavaClass - { - public: - explicit JavaRTCRtpSynchronizationSourceClass(JNIEnv * env); - - jclass cls; - jmethodID ctor; - jfieldID voiceActivityFlag; - }; - - JavaLocalRef toJava(JNIEnv * env, const webrtc::RtpSource & source); - webrtc::RtpSource toNative(JNIEnv * env, const JavaRef & source); - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/api/RTCRtpTransceiverInit.h b/webrtc-jni/src/main/cpp/include/api/RTCRtpTransceiverInit.h deleted file mode 100644 index f8c0908..0000000 --- a/webrtc-jni/src/main/cpp/include/api/RTCRtpTransceiverInit.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_API_RTC_RTP_TRANSCEIVER_INIT_H_ -#define JNI_WEBRTC_API_RTC_RTP_TRANSCEIVER_INIT_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include "api/rtp_transceiver_interface.h" - -#include - -namespace jni -{ - namespace RTCRtpTransceiverInit - { - class JavaRTCRtpTransceiverInitClass : public JavaClass - { - public: - explicit JavaRTCRtpTransceiverInitClass(JNIEnv * env); - - jclass cls; - jfieldID direction; - jfieldID streamIds; - jfieldID sendEncodings; - }; - - webrtc::RtpTransceiverInit toNative(JNIEnv * env, const JavaRef & javaType); - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/api/VideoFrame.h b/webrtc-jni/src/main/cpp/include/api/VideoFrame.h deleted file mode 100644 index 6be8e88..0000000 --- a/webrtc-jni/src/main/cpp/include/api/VideoFrame.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_API_VIDEO_FRAME_H_ -#define JNI_WEBRTC_API_VIDEO_FRAME_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include "api/video/video_frame.h" -#include "api/video/video_frame_buffer.h" - -#include - -namespace jni -{ - namespace VideoFrame - { - webrtc::VideoFrame toNative(JNIEnv * env, const JavaRef & javaFrame); - } - - namespace I420Buffer - { - JavaLocalRef toJava(JNIEnv * env, const webrtc::scoped_refptr & buffer); - } - - class JavaVideoFrameClass : public JavaClass - { - public: - explicit JavaVideoFrameClass(JNIEnv * env); - - jclass cls; - jmethodID ctor; - jfieldID buffer; - jfieldID rotation; - jfieldID timestampNs; - }; - - class JavaNativeI420BufferClass : public JavaClass - { - public: - explicit JavaNativeI420BufferClass(JNIEnv * env); - - jclass cls; - jmethodID ctor; - jfieldID dataY; - jfieldID dataU; - jfieldID dataV; - jfieldID strideY; - jfieldID strideU; - jfieldID strideV; - jfieldID width; - jfieldID height; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/api/VideoTrackSink.h b/webrtc-jni/src/main/cpp/include/api/VideoTrackSink.h deleted file mode 100644 index a224d21..0000000 --- a/webrtc-jni/src/main/cpp/include/api/VideoTrackSink.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_API_VIDEO_TRACK_SINK_H_ -#define JNI_WEBRTC_API_VIDEO_TRACK_SINK_H_ - -#include "api/VideoFrame.h" -#include "JavaClass.h" -#include "JavaRef.h" - -#include "api/video/video_frame.h" -#include "api/video/video_sink_interface.h" - -#include - -namespace jni -{ - class VideoTrackSink : public webrtc::VideoSinkInterface - { - public: - VideoTrackSink(JNIEnv * env, const JavaGlobalRef & sink); - ~VideoTrackSink() = default; - - // VideoSinkInterface implementation. - void OnFrame(const webrtc::VideoFrame & frame) override; - - private: - class JavaVideoTrackSinkClass : public JavaClass - { - public: - JavaVideoTrackSinkClass(JNIEnv * env); - - jmethodID onFrame; - }; - - private: - JavaGlobalRef sink; - - const std::shared_ptr javaClass; - const std::shared_ptr javaFrameClass; - const std::shared_ptr javaBufferClass; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/Device.h b/webrtc-jni/src/main/cpp/include/media/Device.h deleted file mode 100644 index a8f5896..0000000 --- a/webrtc-jni/src/main/cpp/include/media/Device.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_DEVICE_H_ -#define JNI_WEBRTC_MEDIA_DEVICE_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include -#include -#include - -namespace jni -{ - namespace avdev - { - /** - DeviceTransport and DeviceFormFactor only for audio devices. - */ - enum class DeviceTransport { - trUnknown, - trHdmi, - trUsb, - trWireless, - }; - - enum class DeviceFormFactor { - ffUnknown, - ffSpeaker, - ffMicrophone, - ffHeadset, - ffHeadphone - }; - - class Device - { - public: - virtual ~Device() {}; - - virtual bool operator==(const Device & other); - virtual bool operator!=(const Device & other); - virtual bool operator<(const Device & other); - - std::string getName() const; - std::string getDescriptor() const; - DeviceTransport getDeviceTransport(); - DeviceFormFactor getDeviceFormFactor(); - void setDeviceTransport(DeviceTransport deviceTransport); - void setDeviceFormFactor(DeviceFormFactor deviceFormFactor); - - protected: - Device(std::string name, std::string descriptor); - - private: - const std::string name; - const std::string descriptor; - DeviceTransport deviceTransport; - DeviceFormFactor deviceFormFactor; - }; - - - using DevicePtr = std::shared_ptr; - } - - namespace Device - { - class JavaDeviceClass : public JavaClass - { - public: - explicit JavaDeviceClass(JNIEnv * env); - - jclass cls; - jmethodID ctor; - jfieldID name; - jfieldID descriptor; - jfieldID deviceTransport; - jfieldID deviceFormFactor; - }; - - JavaLocalRef toJavaDevice(JNIEnv * env, avdev::DevicePtr device); - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/DeviceChangeListener.h b/webrtc-jni/src/main/cpp/include/media/DeviceChangeListener.h deleted file mode 100644 index 65a5a9f..0000000 --- a/webrtc-jni/src/main/cpp/include/media/DeviceChangeListener.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_DEVICE_CHANGE_LISTENER_H_ -#define JNI_WEBRTC_MEDIA_DEVICE_CHANGE_LISTENER_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include "media/DeviceHotplugListener.h" - -#include -#include - -namespace jni -{ - - class DeviceChangeListener : public avdev::DeviceHotplugListener - { - public: - explicit DeviceChangeListener(JNIEnv * env, const JavaGlobalRef & listener); - ~DeviceChangeListener() = default; - - // DeviceHotplugListener implementation. - void deviceConnected(avdev::DevicePtr device) override; - void deviceDisconnected(avdev::DevicePtr device) override; - - private: - class JavaDeviceChangeListenerClass : public JavaClass - { - public: - explicit JavaDeviceChangeListenerClass(JNIEnv * env); - - jmethodID deviceConnected; - jmethodID deviceDisconnected; - }; - - private: - JavaGlobalRef listener; - - const std::shared_ptr javaClass; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/DeviceHotplugListener.h b/webrtc-jni/src/main/cpp/include/media/DeviceHotplugListener.h deleted file mode 100644 index cdc3071..0000000 --- a/webrtc-jni/src/main/cpp/include/media/DeviceHotplugListener.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_DEVICE_HOTPLUG_LISTENER_H_ -#define JNI_WEBRTC_MEDIA_DEVICE_HOTPLUG_LISTENER_H_ - -#include "media/Device.h" - -#include - -namespace jni -{ - namespace avdev - { - class DeviceHotplugListener - { - public: - virtual ~DeviceHotplugListener() {}; - - virtual void deviceConnected(DevicePtr device) = 0; - virtual void deviceDisconnected(DevicePtr device) = 0; - }; - - - using PDeviceHotplugListener = std::shared_ptr; - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/DeviceList.h b/webrtc-jni/src/main/cpp/include/media/DeviceList.h deleted file mode 100644 index b6b9178..0000000 --- a/webrtc-jni/src/main/cpp/include/media/DeviceList.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_DEVICE_LIST_H_ -#define JNI_WEBRTC_MEDIA_DEVICE_LIST_H_ - -#include -#include -#include - -namespace jni -{ - template - class DeviceList - { - public: - DeviceList() = default; - virtual ~DeviceList() = default; - - bool insertDevice(T device) - { - std::unique_lock mlock(mutex); - auto result = devicesSet.insert(device); - mlock.unlock(); - - return result.second; - } - - bool removeDevice(T device) - { - std::unique_lock mlock(mutex); - size_t result = devicesSet.erase(device); - mlock.unlock(); - - return result; - } - - T removeDevice(std::function pred) - { - T device = nullptr; - - std::unique_lock mlock(mutex); - - for (auto it = devicesSet.begin(), end = devicesSet.end(); it != end; ) { - if (pred(*it)) { - device = *it; - devicesSet.erase(it); - break; - } - else { - ++it; - } - } - - mlock.unlock(); - - return device; - } - - template - T findDevice(Predicate pred) - { - T device = nullptr; - - std::unique_lock mlock(mutex); - - typename std::set::iterator it = std::find_if(devicesSet.begin(), devicesSet.end(), pred); - if (it != devicesSet.end()) { - device = *it; - } - - mlock.unlock(); - - return device; - } - - bool empty() - { - std::unique_lock mlock(mutex); - - return devicesSet.empty(); - } - - void clearDevices() - { - std::unique_lock mlock(mutex); - devicesSet.clear(); - mlock.unlock(); - } - - std::set devices() - { - std::unique_lock mlock(mutex); - - return devicesSet; - } - - private: - std::set devicesSet; - std::mutex mutex; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/DeviceManager.h b/webrtc-jni/src/main/cpp/include/media/DeviceManager.h deleted file mode 100644 index a4482ff..0000000 --- a/webrtc-jni/src/main/cpp/include/media/DeviceManager.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_DEVICE_MANAGER_H_ -#define JNI_WEBRTC_MEDIA_DEVICE_MANAGER_H_ - -#include -#include - -#include "media/DeviceHotplugListener.h" - -namespace jni -{ - namespace avdev - { - enum DeviceEvent - { - Connected, - Disconnected - }; - - class DeviceManager - { - public: - virtual ~DeviceManager() {}; - - void attachHotplugListener(PDeviceHotplugListener listener); - void detachHotplugListener(PDeviceHotplugListener listener); - - protected: - void notifyDeviceConnected(DevicePtr device); - void notifyDeviceDisconnected(DevicePtr device); - - private: - void notifyListeners(DevicePtr device, const DeviceEvent event); - - std::list> hotplugListeners; - }; - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/MediaStreamTrackObserver.h b/webrtc-jni/src/main/cpp/include/media/MediaStreamTrackObserver.h deleted file mode 100644 index 041fde2..0000000 --- a/webrtc-jni/src/main/cpp/include/media/MediaStreamTrackObserver.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2022 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_STREAM_TRACK_LISTENER_H_ -#define JNI_WEBRTC_MEDIA_STREAM_TRACK_LISTENER_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include "api/media_stream_interface.h" - -#include -#include - -namespace jni -{ - enum class MediaStreamTrackEvent { - ended, - mute - }; - - class MediaStreamTrackObserver : public webrtc::ObserverInterface - { - public: - explicit MediaStreamTrackObserver(JNIEnv * env, const JavaGlobalRef & javaTrack, const webrtc::MediaStreamTrackInterface * track, const MediaStreamTrackEvent & eventType); - ~MediaStreamTrackObserver() = default; - - // ObserverInterface implementation. - void OnChanged() override; - - private: - class JavaMediaStreamTrackListenerClass : public JavaClass - { - public: - explicit JavaMediaStreamTrackListenerClass(JNIEnv * env); - - jmethodID onTrackEnd; - jmethodID onTrackMute; - }; - - JavaLocalRef createJavaTrack(JNIEnv * env); - - private: - const JavaGlobalRef javaTrack; - const webrtc::MediaStreamTrackInterface * track; - const MediaStreamTrackEvent eventType; - const std::shared_ptr javaClass; - webrtc::MediaStreamTrackInterface::TrackState trackState; - bool trackEnabled; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/SyncClock.h b/webrtc-jni/src/main/cpp/include/media/SyncClock.h deleted file mode 100644 index 283a933..0000000 --- a/webrtc-jni/src/main/cpp/include/media/SyncClock.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_SYNC_CLOCK_H_ -#define JNI_WEBRTC_MEDIA_SYNC_CLOCK_H_ - -#include "system_wrappers/include/clock.h" -#include "system_wrappers/include/ntp_time.h" - -#include - -namespace jni -{ - // Synchronized Clock for A/V timing - class SyncClock - { - public: - SyncClock(); - - // Get current timestamp in microseconds - int64_t GetTimestampUs() const; - - // Get current timestamp in milliseconds - int64_t GetTimestampMs() const; - - // Get NTP timestamp for RTP synchronization - webrtc::NtpTime GetNtpTime() const; - - private: - std::chrono::steady_clock::time_point start_time_; - }; -} -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/audio/AudioConverter.h b/webrtc-jni/src/main/cpp/include/media/audio/AudioConverter.h deleted file mode 100644 index fa496ec..0000000 --- a/webrtc-jni/src/main/cpp/include/media/audio/AudioConverter.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_AUDIO_CONVERTER_H_ -#define JNI_WEBRTC_MEDIA_AUDIO_CONVERTER_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include - -namespace jni -{ - class AudioConverter - { - public: - AudioConverter(const AudioConverter&) = delete; - AudioConverter& operator=(const AudioConverter&) = delete; - - static std::unique_ptr create(size_t srcFrames, size_t srcChannels, size_t dstFrames, size_t dstChannels); - - virtual ~AudioConverter() = default; - - virtual void convert(const int16_t * src, size_t srcSize, int16_t * dst, size_t dstSize) = 0; - - size_t getSrcChannels() const { return srcChannels; } - size_t getSrcFrames() const { return srcFrames; } - size_t getDstChannels() const { return dstChannels; } - size_t getDstFrames() const { return dstFrames; } - - protected: - AudioConverter(); - AudioConverter(size_t srcFrames, size_t srcChannels, size_t dstFrames, size_t dstChannels); - - void checkSizes(size_t srcSize, size_t dstCapacity) const; - - const size_t srcFrames; - const size_t srcChannels; - const size_t dstFrames; - const size_t dstChannels; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/audio/AudioDevice.h b/webrtc-jni/src/main/cpp/include/media/audio/AudioDevice.h deleted file mode 100644 index 2edf487..0000000 --- a/webrtc-jni/src/main/cpp/include/media/audio/AudioDevice.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_AUDIO_DEVICE_H_ -#define JNI_WEBRTC_MEDIA_AUDIO_DEVICE_H_ - -#include "media/Device.h" -#include "JavaClass.h" -#include "JavaRef.h" - -#include - -namespace jni -{ - namespace avdev - { - - enum class AudioDeviceDirectionType { - adtUnknown, - adtCapture, - adtRender - }; - - class AudioDevice : public Device - { - public: - AudioDevice(std::string name, std::string descriptor); - virtual ~AudioDevice() {}; - AudioDeviceDirectionType directionType; - }; - } - - namespace AudioDevice - { - class JavaAudioDeviceClass : public JavaClass - { - public: - explicit JavaAudioDeviceClass(JNIEnv * env); - - jclass cls; - jmethodID ctor; - jfieldID name; - jfieldID descriptor; - jfieldID deviceTransport; - jfieldID deviceFormFactor; - jfieldID directionType; - }; - - JavaLocalRef toJavaAudioDevice(JNIEnv * env, avdev::DevicePtr device); - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/audio/AudioDeviceManager.h b/webrtc-jni/src/main/cpp/include/media/audio/AudioDeviceManager.h deleted file mode 100644 index e2b3f5a..0000000 --- a/webrtc-jni/src/main/cpp/include/media/audio/AudioDeviceManager.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_AUDIO_DEVICE_MANAGER_H_ -#define JNI_WEBRTC_MEDIA_AUDIO_DEVICE_MANAGER_H_ - -#include "media/DeviceManager.h" -#include "media/DeviceList.h" -#include "media/audio/AudioDevice.h" - -#include -#include - -namespace jni -{ - namespace avdev - { - using AudioDevicePtr = std::shared_ptr; - - - class AudioDeviceManager : public DeviceManager - { - public: - AudioDeviceManager(); - virtual ~AudioDeviceManager() {}; - - virtual AudioDevicePtr getDefaultAudioCaptureDevice(); - virtual AudioDevicePtr getDefaultAudioPlaybackDevice(); - - virtual std::set getAudioCaptureDevices() = 0; - virtual std::set getAudioPlaybackDevices() = 0; - - protected: - void setDefaultCaptureDevice(AudioDevicePtr device); - AudioDevicePtr getDefaultCaptureDevice(); - - void setDefaultPlaybackDevice(AudioDevicePtr device); - AudioDevicePtr getDefaultPlaybackDevice(); - - DeviceList captureDevices; - DeviceList playbackDevices; - - private: - AudioDevicePtr defaultCaptureDevice; - AudioDevicePtr defaultPlaybackDevice; - std::mutex mutex; - }; - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/audio/AudioProcessing.h b/webrtc-jni/src/main/cpp/include/media/audio/AudioProcessing.h deleted file mode 100644 index 4accfae..0000000 --- a/webrtc-jni/src/main/cpp/include/media/audio/AudioProcessing.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_AUDIO_PROCESSING_H_ -#define JNI_WEBRTC_MEDIA_AUDIO_PROCESSING_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include "modules/audio_processing/include/audio_processing.h" - -#include - -namespace jni -{ - namespace AudioProcessing - { - class JavaAudioProcessingClass : public JavaClass - { - public: - explicit JavaAudioProcessingClass(JNIEnv * env); - - jclass cls; - jfieldID stats; - }; - - void updateStats(const webrtc::AudioProcessingStats & stats, JNIEnv * env, const JavaRef & javaType); - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/audio/AudioProcessingConfig.h b/webrtc-jni/src/main/cpp/include/media/audio/AudioProcessingConfig.h deleted file mode 100644 index 5fb98d1..0000000 --- a/webrtc-jni/src/main/cpp/include/media/audio/AudioProcessingConfig.h +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_AUDIO_PROCESSING_CONFIG_H_ -#define JNI_WEBRTC_MEDIA_AUDIO_PROCESSING_CONFIG_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include "modules/audio_processing/include/audio_processing.h" - -#include - -namespace jni -{ - namespace AudioProcessingConfig - { - class JavaAudioProcessingConfigClass : public JavaClass - { - public: - explicit JavaAudioProcessingConfigClass(JNIEnv * env); - - jclass cls; - jfieldID pipeline; - jfieldID echoCanceller; - jfieldID gainController; - jfieldID gainControllerDigital; - jfieldID highPassFilter; - jfieldID noiseSuppression; - jfieldID captureLevelAdjustment; - }; - - webrtc::AudioProcessing::Config toNative(JNIEnv * env, const JavaRef & javaType); - webrtc::AudioProcessing::Config::Pipeline toPipeline(JNIEnv* env, const JavaLocalRef & javaType); - webrtc::AudioProcessing::Config::GainController1 toGainController1(JNIEnv * env, const JavaLocalRef & javaType); - webrtc::AudioProcessing::Config::GainController2 toGainController2(JNIEnv * env, const JavaLocalRef & javaType); - - - class JavaPipelineClass : public JavaClass - { - public: - explicit JavaPipelineClass(JNIEnv * env); - - jclass cls; - jfieldID maximumInternalProcessingRate; - jfieldID multiChannelRender; - jfieldID multiChannelCapture; - jfieldID captureDownmixMethod; - }; - - class JavaEchoCancellerClass : public JavaClass - { - public: - explicit JavaEchoCancellerClass(JNIEnv * env); - - jclass cls; - jfieldID enabled; - jfieldID enforceHighPassFiltering; - }; - - class JavaGainControllerDigitalClass : public JavaClass - { - public: - explicit JavaGainControllerDigitalClass(JNIEnv * env); - - jclass cls; - jfieldID enabled; - jfieldID inputVolumeController; - jfieldID fixedDigital; - jfieldID adaptiveDigital; - }; - - class JavaInputVolumeControllerClass : public JavaClass - { - public: - explicit JavaInputVolumeControllerClass(JNIEnv * env); - - jclass cls; - jfieldID enabled; - }; - - class JavaGainControlFixedDigitalClass : public JavaClass - { - public: - explicit JavaGainControlFixedDigitalClass(JNIEnv * env); - - jclass cls; - jfieldID gainDb; - }; - - class JavaGainControlAdaptiveDigitalClass : public JavaClass - { - public: - explicit JavaGainControlAdaptiveDigitalClass(JNIEnv * env); - - jclass cls; - jfieldID enabled; - jfieldID headroomDb; - jfieldID maxGainDb; - jfieldID initialGainDb; - jfieldID maxGainChangeDbPerSecond; - jfieldID maxOutputNoiseLevelDbfs; - }; - - class JavaGainControllerClass : public JavaClass - { - public: - explicit JavaGainControllerClass(JNIEnv * env); - - jclass cls; - jfieldID enabled; - jfieldID targetLevelDbfs; - jfieldID compressionGainDb; - jfieldID enableLimiter; - jfieldID mode; - jfieldID analogGainController; - }; - - class JavaAgc1AnalogGainControllerClass : public JavaClass - { - public: - explicit JavaAgc1AnalogGainControllerClass(JNIEnv * env); - - jclass cls; - jfieldID enabled; - jfieldID startupMinVolume; - jfieldID clippedLevelMin; - jfieldID enableDigitalAdaptive; - jfieldID clippedLevelStep; - jfieldID clippedRatioThreshold; - jfieldID clippedWaitFrames; - jfieldID clippingPredictor; - }; - - class JavaAgc1ClippingPredictorClass : public JavaClass - { - public: - explicit JavaAgc1ClippingPredictorClass(JNIEnv * env); - - jclass cls; - jfieldID enabled; - jfieldID mode; - jfieldID windowLength; - jfieldID referenceWindowLength; - jfieldID referenceWindowDelay; - jfieldID clippingThreshold; - jfieldID crestFactorMargin; - jfieldID usePredictedStep; - }; - - class JavaHighPassFilterClass : public JavaClass - { - public: - explicit JavaHighPassFilterClass(JNIEnv * env); - - jclass cls; - jfieldID enabled; - }; - - class JavaNoiseSuppressionClass : public JavaClass - { - public: - explicit JavaNoiseSuppressionClass(JNIEnv * env); - - jclass cls; - jfieldID enabled; - jfieldID level; - }; - - class JavaCaptureLevelAdjustmentClass : public JavaClass - { - public: - explicit JavaCaptureLevelAdjustmentClass(JNIEnv * env); - - jclass cls; - jfieldID enabled; - jfieldID preGainFactor; - jfieldID postGainFactor; - jfieldID analogMicGainEmulation; - }; - - class JavaAnalogMicGainEmulationClass : public JavaClass - { - public: - explicit JavaAnalogMicGainEmulationClass(JNIEnv * env); - - jclass cls; - jfieldID enabled; - jfieldID initialLevel; - }; - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/audio/AudioProcessingStats.h b/webrtc-jni/src/main/cpp/include/media/audio/AudioProcessingStats.h deleted file mode 100644 index 6b277aa..0000000 --- a/webrtc-jni/src/main/cpp/include/media/audio/AudioProcessingStats.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_AUDIO_PROCESSING_STATS_H_ -#define JNI_WEBRTC_MEDIA_AUDIO_PROCESSING_STATS_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include "modules/audio_processing/include/audio_processing.h" - -#include - -namespace jni -{ - namespace AudioProcessingStats - { - class JavaAudioProcessingStatsClass : public JavaClass - { - public: - explicit JavaAudioProcessingStatsClass(JNIEnv * env); - - jclass cls; - jfieldID echoReturnLoss; - jfieldID echoReturnLossEnhancement; - jfieldID divergentFilterFraction; - jfieldID delayMs; - jfieldID delayMedianMs; - jfieldID delayStandardDeviationMs; - jfieldID residualEchoLikelihood; - jfieldID residualEchoLikelihoodRecentMax; - }; - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/audio/AudioProcessingStreamConfig.h b/webrtc-jni/src/main/cpp/include/media/audio/AudioProcessingStreamConfig.h deleted file mode 100644 index 851df9d..0000000 --- a/webrtc-jni/src/main/cpp/include/media/audio/AudioProcessingStreamConfig.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_AUDIO_PROCESSING_STREAM_CONFIG_H_ -#define JNI_WEBRTC_MEDIA_AUDIO_PROCESSING_STREAM_CONFIG_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include "modules/audio_processing/include/audio_processing.h" - -#include - -namespace jni -{ - namespace AudioProcessingStreamConfig - { - class JavaAudioProcessingStreamConfigClass : public JavaClass - { - public: - explicit JavaAudioProcessingStreamConfigClass(JNIEnv * env); - - jclass cls; - jmethodID ctor; - jfieldID sampleRate; - jfieldID channels; - }; - - webrtc::StreamConfig toNative(JNIEnv * env, const JavaRef & javaType); - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/audio/AudioSink.h b/webrtc-jni/src/main/cpp/include/media/audio/AudioSink.h deleted file mode 100644 index 30d501c..0000000 --- a/webrtc-jni/src/main/cpp/include/media/audio/AudioSink.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_AUDIO_SINK_H_ -#define JNI_WEBRTC_MEDIA_AUDIO_SINK_H_ - -#include "modules/audio_device/include/audio_device_defines.h" - -namespace jni -{ - class AudioSink : public webrtc::AudioTransport - { - public: - virtual ~AudioSink() {}; - - int32_t NeedMorePlayData(const size_t nSamples, - const size_t nBytesPerSample, - const size_t nChannels, - const uint32_t samplesPerSec, - void* audioSamples, - size_t& nSamplesOut, - int64_t* elapsed_time_ms, - int64_t* ntp_time_ms) - { - *elapsed_time_ms = 0; - *ntp_time_ms = 0; - - return 0; - } - - void PullRenderData(int bits_per_sample, - int sample_rate, - size_t number_of_channels, - size_t number_of_frames, - void* audio_data, - int64_t* elapsed_time_ms, - int64_t* ntp_time_ms) - { - } - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/audio/AudioSource.h b/webrtc-jni/src/main/cpp/include/media/audio/AudioSource.h deleted file mode 100644 index b5b68f5..0000000 --- a/webrtc-jni/src/main/cpp/include/media/audio/AudioSource.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_AUDIO_SOURCE_H_ -#define JNI_WEBRTC_MEDIA_AUDIO_SOURCE_H_ - -#include "modules/audio_device/include/audio_device_defines.h" - -namespace jni -{ - class AudioSource : public webrtc::AudioTransport - { - public: - virtual ~AudioSource() {}; - - int32_t RecordedDataIsAvailable(const void* audioSamples, - const size_t nSamples, - const size_t nBytesPerSample, - const size_t nChannels, - const uint32_t samplesPerSec, - const uint32_t totalDelayMS, - const int32_t clockDrift, - const uint32_t currentMicLevel, - const bool keyPressed, - uint32_t& newMicLevel) - { - return 0; - } - - void PullRenderData(int bits_per_sample, - int sample_rate, - size_t number_of_channels, - size_t number_of_frames, - void* audio_data, - int64_t* elapsed_time_ms, - int64_t* ntp_time_ms) - { - } - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/audio/AudioTransportSink.h b/webrtc-jni/src/main/cpp/include/media/audio/AudioTransportSink.h deleted file mode 100644 index a7b76aa..0000000 --- a/webrtc-jni/src/main/cpp/include/media/audio/AudioTransportSink.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_API_AUDIO_TRANSPORT_SINK_H_ -#define JNI_WEBRTC_API_AUDIO_TRANSPORT_SINK_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include "AudioSink.h" - -#include - -namespace jni -{ - class AudioTransportSink : public AudioSink - { - public: - AudioTransportSink(JNIEnv * env, const JavaGlobalRef & sink); - ~AudioTransportSink() = default; - - // AudioTransport implementation. - int32_t RecordedDataIsAvailable( - const void * audioSamples, - const size_t nSamples, - const size_t nBytesPerSample, - const size_t nChannels, - const uint32_t samplesPerSec, - const uint32_t totalDelayMS, - const int32_t clockDrift, - const uint32_t currentMicLevel, - const bool keyPressed, - uint32_t & newMicLevel) override; - - private: - class JavaAudioSinkClass : public JavaClass - { - public: - explicit JavaAudioSinkClass(JNIEnv * env); - - jmethodID onRecordedData; - }; - - private: - JavaGlobalRef sink; - - const std::shared_ptr javaClass; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/audio/AudioTransportSource.h b/webrtc-jni/src/main/cpp/include/media/audio/AudioTransportSource.h deleted file mode 100644 index 3af8fd1..0000000 --- a/webrtc-jni/src/main/cpp/include/media/audio/AudioTransportSource.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_API_AUDIO_TRANSPORT_SOURCE_H_ -#define JNI_WEBRTC_API_AUDIO_TRANSPORT_SOURCE_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include "AudioSource.h" - -#include - -namespace jni -{ - class AudioTransportSource : public AudioSource - { - public: - AudioTransportSource(JNIEnv * env, const JavaGlobalRef & sink); - ~AudioTransportSource() = default; - - // AudioTransport implementation. - int32_t NeedMorePlayData( - const size_t nSamples, - const size_t nBytesPerSample, - const size_t nChannels, - const uint32_t samplesPerSec, - void * audioSamples, - size_t & nSamplesOut, - int64_t * elapsed_time_ms, - int64_t * ntp_time_ms) override; - - private: - class JavaAudioSourceClass : public JavaClass - { - public: - explicit JavaAudioSourceClass(JNIEnv * env); - - jmethodID onPlaybackData; - }; - - private: - JavaGlobalRef source; - JavaGlobalRef buffer; - - const std::shared_ptr javaClass; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/audio/CustomAudioSource.h b/webrtc-jni/src/main/cpp/include/media/audio/CustomAudioSource.h deleted file mode 100644 index 5667972..0000000 --- a/webrtc-jni/src/main/cpp/include/media/audio/CustomAudioSource.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_API_AUDIO_CUSTOM_AUDIO_SOURCE_H_ -#define JNI_WEBRTC_API_AUDIO_CUSTOM_AUDIO_SOURCE_H_ - -#include "api/media_stream_interface.h" -#include "rtc_base/ref_counted_object.h" - -#include "media/SyncClock.h" - -#include -#include -#include - -namespace jni -{ - class CustomAudioSource : public webrtc::AudioSourceInterface - { - public: - explicit CustomAudioSource(std::shared_ptr clock); - - // AudioSourceInterface implementation - void RegisterObserver(webrtc::ObserverInterface * observer) override; - void UnregisterObserver(webrtc::ObserverInterface * observer) override; - void AddSink(webrtc::AudioTrackSinkInterface * sink) override; - void RemoveSink(webrtc::AudioTrackSinkInterface * sink) override; - SourceState state() const override; - bool remote() const override; - - // Push audio data with synchronization - void PushAudioData(const void * audio_data, int bits_per_sample, - int sample_rate, size_t number_of_channels, - size_t number_of_frames); - - // Set audio capture delay for synchronization adjustment - void SetAudioCaptureDelay(int64_t delay_us); - - private: - std::vector sinks_; - std::shared_ptr clock_; - //webrtc::CriticalSection crit_; - std::atomic total_samples_captured_; - int64_t audio_capture_delay_us_; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/audio/RawAudioFileSink.h b/webrtc-jni/src/main/cpp/include/media/audio/RawAudioFileSink.h deleted file mode 100644 index 9e445f8..0000000 --- a/webrtc-jni/src/main/cpp/include/media/audio/RawAudioFileSink.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_RAW_AUDIO_FILE_SINK_H_ -#define JNI_WEBRTC_MEDIA_RAW_AUDIO_FILE_SINK_H_ - -#include "AudioSink.h" - -#include -#include -#include - -namespace jni -{ - class RawAudioFileSink : public AudioSink - { - public: - RawAudioFileSink(std::string fileName); - ~RawAudioFileSink(); - - int32_t RecordedDataIsAvailable( - const void * audioSamples, - const size_t nSamples, - const size_t nBytesPerSample, - const size_t nChannels, - const uint32_t samplesPerSec, - const uint32_t totalDelayMS, - const int32_t clockDrift, - const uint32_t currentMicLevel, - const bool keyPressed, - uint32_t & newMicLevel) override; - - private: - std::ofstream outputStream; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/audio/RawAudioFileSource.h b/webrtc-jni/src/main/cpp/include/media/audio/RawAudioFileSource.h deleted file mode 100644 index 4b7a16d..0000000 --- a/webrtc-jni/src/main/cpp/include/media/audio/RawAudioFileSource.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_RAW_AUDIO_FILE_SOURCE_H_ -#define JNI_WEBRTC_MEDIA_RAW_AUDIO_FILE_SOURCE_H_ - -#include "AudioSource.h" - -#include -#include - -namespace jni -{ - class RawAudioFileSource : public AudioSource - { - public: - RawAudioFileSource(std::string fileName); - ~RawAudioFileSource(); - - int32_t NeedMorePlayData( - const size_t nSamples, - const size_t nBytesPerSample, - const size_t nChannels, - const uint32_t samplesPerSec, - void * audioSamples, - size_t & nSamplesOut, - int64_t * elapsed_time_ms, - int64_t * ntp_time_ms) override; - - private: - std::ifstream inputStream; - size_t fileLength; - size_t fileRemainingBytes; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/audio/WavAudioFileSink.h b/webrtc-jni/src/main/cpp/include/media/audio/WavAudioFileSink.h deleted file mode 100644 index 4249c21..0000000 --- a/webrtc-jni/src/main/cpp/include/media/audio/WavAudioFileSink.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_WAV_AUDIO_FILE_SINK_H_ -#define JNI_WEBRTC_MEDIA_WAV_AUDIO_FILE_SINK_H_ - -#include "AudioSink.h" - -#include "common_audio/wav_file.h" - -#include -#include - -#if defined(WEBRTC_MAC) -#define MAYBE_CPP DISABLED_CPP -#define MAYBE_CPPFileDescriptor DISABLED_CPPFileDescriptor -#else -#define MAYBE_CPP CPP -#define MAYBE_CPPFileDescriptor CPPFileDescriptor -#endif - -namespace jni -{ - class WavAudioFileSink : public AudioSink - { - public: - WavAudioFileSink(std::string fileName); - ~WavAudioFileSink(); - - int32_t RecordedDataIsAvailable( - const void * audioSamples, - const size_t nSamples, - const size_t nBytesPerSample, - const size_t nChannels, - const uint32_t samplesPerSec, - const uint32_t totalDelayMS, - const int32_t clockDrift, - const uint32_t currentMicLevel, - const bool keyPressed, - uint32_t & newMicLevel) override; - - private: - std::unique_ptr wavWriter; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/audio/WavAudioFileSource.h b/webrtc-jni/src/main/cpp/include/media/audio/WavAudioFileSource.h deleted file mode 100644 index 2810227..0000000 --- a/webrtc-jni/src/main/cpp/include/media/audio/WavAudioFileSource.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_WAV_AUDIO_FILE_SOURCE_H_ -#define JNI_WEBRTC_MEDIA_WAV_AUDIO_FILE_SOURCE_H_ - -#include "AudioSource.h" - -#include "common_audio/wav_file.h" - -#include -#include - -#if defined(WEBRTC_MAC) -#define MAYBE_CPP DISABLED_CPP -#define MAYBE_CPPFileDescriptor DISABLED_CPPFileDescriptor -#else -#define MAYBE_CPP CPP -#define MAYBE_CPPFileDescriptor CPPFileDescriptor -#endif - -namespace jni -{ - class WavAudioFileSource : public AudioSource - { - public: - WavAudioFileSource(std::string fileName); - ~WavAudioFileSource(); - - int32_t NeedMorePlayData( - const size_t nSamples, - const size_t nBytesPerSample, - const size_t nChannels, - const uint32_t samplesPerSec, - void * audioSamples, - size_t & nSamplesOut, - int64_t * elapsed_time_ms, - int64_t * ntp_time_ms) override; - - private: - std::unique_ptr wavReader; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/audio/linux/PulseAudioDeviceManager.h b/webrtc-jni/src/main/cpp/include/media/audio/linux/PulseAudioDeviceManager.h deleted file mode 100644 index b07b429..0000000 --- a/webrtc-jni/src/main/cpp/include/media/audio/linux/PulseAudioDeviceManager.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_PULSE_AUDIO_DEVICE_MANAGER_H_ -#define JNI_WEBRTC_MEDIA_PULSE_AUDIO_DEVICE_MANAGER_H_ - -#include "media/audio/AudioDeviceManager.h" - -#include -#include - -namespace jni -{ - namespace avdev - { - class PulseAudioDeviceManager : public AudioDeviceManager - { - public: - PulseAudioDeviceManager(); - ~PulseAudioDeviceManager(); - - AudioDevicePtr getDefaultAudioCaptureDevice() override; - AudioDevicePtr getDefaultAudioPlaybackDevice() override; - - std::set getAudioCaptureDevices() override; - std::set getAudioPlaybackDevices() override; - - private: - void dispose(); - - void iterate(pa_threaded_mainloop * main_loop, pa_operation * op); - - /* PulseAudio API callbacks. */ - static void stateCallback(pa_context * ctx, void * userdata); - static void serverInfoCallback(pa_context * ctx, const pa_server_info * info, void * userdata); - static void subscribeCallback(pa_context * ctx, pa_subscription_event_type_t t, uint32_t idx, void * userdata); - static void getSourceInfoCallback(pa_context * ctx, const pa_source_info * info, int last, void * userdata); - static void getSourceCallback(pa_context * ctx, const pa_source_info * info, int last, void * userdata); - static void newSourceCallback(pa_context * ctx, const pa_source_info * info, int last, void * userdata); - static void getSinkInfoCallback(pa_context * ctx, const pa_sink_info * info, int last, void * userdata); - static void getSinkCallback(pa_context * ctx, const pa_sink_info * info, int last, void * userdata); - static void newSinkCallback(pa_context * ctx, const pa_sink_info * info, int last, void * userdata); - - void insertDevice(DeviceList & devices, pa_proplist * proplist, const char * name, const char * desc, uint32_t index, bool notify, bool isCapture); - void removeDevice(DeviceList & devices, uint32_t index, bool isCapture); - - void fillAdditionalTypes(AudioDevicePtr device, pa_proplist * proplist); - DeviceFormFactor getActualFormFactor(std::string formFactor); - DeviceTransport getActualTransport(std::string transport); - - private: - pa_threaded_mainloop * mainloop; - pa_context * context; - - std::string defaultCaptureName; - std::string defaultCaptureDescName; - std::string defaultPlaybackName; - std::string defaultPlaybackDescName; - - std::unordered_map deviceMap; - }; - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/audio/linux/PulseAudioLoader.h b/webrtc-jni/src/main/cpp/include/media/audio/linux/PulseAudioLoader.h deleted file mode 100644 index 4ac742a..0000000 --- a/webrtc-jni/src/main/cpp/include/media/audio/linux/PulseAudioLoader.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef PULSE_AUDIO_LOADER_H -#define PULSE_AUDIO_LOADER_H - -#include -#include -#include -#include "Exception.h" - -namespace jni -{ - namespace avdev - { - typedef pa_threaded_mainloop* (*pa_threaded_mainloop_new_t)(); - typedef void (*pa_threaded_mainloop_free_t)(pa_threaded_mainloop* m); - typedef int (*pa_threaded_mainloop_start_t)(pa_threaded_mainloop* m); - typedef void (*pa_threaded_mainloop_stop_t)(pa_threaded_mainloop* m); - typedef pa_mainloop_api* (*pa_threaded_mainloop_get_api_t)(pa_threaded_mainloop* m); - typedef void (*pa_threaded_mainloop_lock_t)(pa_threaded_mainloop* m); - typedef void (*pa_threaded_mainloop_unlock_t)(pa_threaded_mainloop* m); - typedef void (*pa_threaded_mainloop_wait_t)(pa_threaded_mainloop* m); - typedef void (*pa_threaded_mainloop_signal_t)(pa_threaded_mainloop* m, int wait_for_accept); - typedef int (*pa_threaded_mainloop_in_thread_t)(pa_threaded_mainloop* m); - - typedef pa_context* (*pa_context_new_t)(pa_mainloop_api* mainloop, const char* name); - typedef void (*pa_context_unref_t)(pa_context* c); - typedef void (*pa_context_set_state_callback_t)(pa_context* c, pa_context_notify_cb_t cb, void* userdata); - typedef void (*pa_context_set_subscribe_callback_t)(pa_context* c, pa_context_subscribe_cb_t cb, void* userdata); - typedef int (*pa_context_connect_t)(pa_context* c, const char* server, pa_context_flags_t flags, const pa_spawn_api* api); - typedef void (*pa_context_disconnect_t)(pa_context* c); - typedef pa_context_state_t (*pa_context_get_state_t)(const pa_context* c); - typedef pa_operation* (*pa_context_subscribe_t)(pa_context* c, pa_subscription_mask_t m, pa_context_success_cb_t cb, void* userdata); - typedef pa_operation* (*pa_context_get_server_info_t)(pa_context* c, pa_server_info_cb_t cb, void* userdata); - typedef pa_operation* (*pa_context_get_source_info_by_name_t)(pa_context* c, const char* name, pa_source_info_cb_t cb, void* userdata); - typedef pa_operation* (*pa_context_get_source_info_list_t)(pa_context* c, pa_source_info_cb_t cb, void* userdata); - typedef pa_operation* (*pa_context_get_source_info_by_index_t)(pa_context* c, uint32_t idx, pa_source_info_cb_t cb, void* userdata); - typedef pa_operation* (*pa_context_get_sink_info_by_name_t)(pa_context* c, const char* name, pa_sink_info_cb_t cb, void* userdata); - typedef pa_operation* (*pa_context_get_sink_info_list_t)(pa_context* c, pa_sink_info_cb_t cb, void* userdata); - typedef pa_operation* (*pa_context_get_sink_info_by_index_t)(pa_context* c, uint32_t idx, pa_sink_info_cb_t cb, void* userdata); - - typedef void (*pa_operation_unref_t)(pa_operation* o); - typedef pa_operation_state_t (*pa_operation_get_state_t)(const pa_operation* o); - typedef const char* (*pa_proplist_gets_t)(const pa_proplist* p, const char* key); - - class PulseAudioLoader { - public: - static PulseAudioLoader& instance() { - static PulseAudioLoader instance; - return instance; - } - - bool load() { - if (loaded) return true; - - // Try to open the library - lib_handle = dlopen("libpulse.so.0", RTLD_NOW); - if (!lib_handle) return false; - - #define LOAD_SYM(name) \ - name = (name##_t)dlsym(lib_handle, #name); \ - if (!name) { close(); return false; } - - LOAD_SYM(pa_threaded_mainloop_new); - LOAD_SYM(pa_threaded_mainloop_free); - LOAD_SYM(pa_threaded_mainloop_start); - LOAD_SYM(pa_threaded_mainloop_stop); - LOAD_SYM(pa_threaded_mainloop_get_api); - LOAD_SYM(pa_threaded_mainloop_lock); - LOAD_SYM(pa_threaded_mainloop_unlock); - LOAD_SYM(pa_threaded_mainloop_wait); - LOAD_SYM(pa_threaded_mainloop_signal); - LOAD_SYM(pa_threaded_mainloop_in_thread); - - LOAD_SYM(pa_context_new); - LOAD_SYM(pa_context_unref); - LOAD_SYM(pa_context_set_state_callback); - LOAD_SYM(pa_context_set_subscribe_callback); - LOAD_SYM(pa_context_connect); - LOAD_SYM(pa_context_disconnect); - LOAD_SYM(pa_context_get_state); - LOAD_SYM(pa_context_subscribe); - - LOAD_SYM(pa_context_get_server_info); - LOAD_SYM(pa_context_get_source_info_by_name); - LOAD_SYM(pa_context_get_source_info_list); - LOAD_SYM(pa_context_get_source_info_by_index); - LOAD_SYM(pa_context_get_sink_info_by_name); - LOAD_SYM(pa_context_get_sink_info_list); - LOAD_SYM(pa_context_get_sink_info_by_index); - - LOAD_SYM(pa_operation_unref); - LOAD_SYM(pa_operation_get_state); - LOAD_SYM(pa_proplist_gets); - - loaded = true; - return true; - } - - void close() { - if (lib_handle) { - dlclose(lib_handle); - lib_handle = nullptr; - } - loaded = false; - } - - bool isLoaded() const { return loaded; } - - pa_threaded_mainloop_new_t pa_threaded_mainloop_new; - pa_threaded_mainloop_free_t pa_threaded_mainloop_free; - pa_threaded_mainloop_start_t pa_threaded_mainloop_start; - pa_threaded_mainloop_stop_t pa_threaded_mainloop_stop; - pa_threaded_mainloop_get_api_t pa_threaded_mainloop_get_api; - pa_threaded_mainloop_lock_t pa_threaded_mainloop_lock; - pa_threaded_mainloop_unlock_t pa_threaded_mainloop_unlock; - pa_threaded_mainloop_wait_t pa_threaded_mainloop_wait; - pa_threaded_mainloop_signal_t pa_threaded_mainloop_signal; - pa_threaded_mainloop_in_thread_t pa_threaded_mainloop_in_thread; - - pa_context_new_t pa_context_new; - pa_context_unref_t pa_context_unref; - pa_context_set_state_callback_t pa_context_set_state_callback; - pa_context_set_subscribe_callback_t pa_context_set_subscribe_callback; - pa_context_connect_t pa_context_connect; - pa_context_disconnect_t pa_context_disconnect; - pa_context_get_state_t pa_context_get_state; - pa_context_subscribe_t pa_context_subscribe; - - pa_context_get_server_info_t pa_context_get_server_info; - pa_context_get_source_info_by_name_t pa_context_get_source_info_by_name; - pa_context_get_source_info_list_t pa_context_get_source_info_list; - pa_context_get_source_info_by_index_t pa_context_get_source_info_by_index; - pa_context_get_sink_info_by_name_t pa_context_get_sink_info_by_name; - pa_context_get_sink_info_list_t pa_context_get_sink_info_list; - pa_context_get_sink_info_by_index_t pa_context_get_sink_info_by_index; - - pa_operation_unref_t pa_operation_unref; - pa_operation_get_state_t pa_operation_get_state; - pa_proplist_gets_t pa_proplist_gets; - - private: - PulseAudioLoader() : loaded(false), lib_handle(nullptr) {} - bool loaded; - void* lib_handle; - }; - } // namespace avdev -} // namespace jni - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/audio/macos/CoreAudioDeviceManager.h b/webrtc-jni/src/main/cpp/include/media/audio/macos/CoreAudioDeviceManager.h deleted file mode 100644 index 7eb36f2..0000000 --- a/webrtc-jni/src/main/cpp/include/media/audio/macos/CoreAudioDeviceManager.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_CORE_AUDIO_DEVICE_MANAGER_H_ -#define JNI_WEBRTC_MEDIA_CORE_AUDIO_DEVICE_MANAGER_H_ - -#include "media/audio/AudioDeviceManager.h" - -#include - -namespace jni -{ - namespace avdev - { - class CoreAudioDeviceManager : public AudioDeviceManager - { - public: - CoreAudioDeviceManager(); - ~CoreAudioDeviceManager(); - - std::set getAudioCaptureDevices() override; - std::set getAudioPlaybackDevices() override; - - AudioDevicePtr getDefaultAudioCaptureDevice() override; - AudioDevicePtr getDefaultAudioPlaybackDevice() override; - - private: - void enumerateDevices(const AudioObjectPropertyScope & scope); - void onDevicesChanged(); - void onDefaultDeviceChanged(const AudioObjectPropertyScope & scope, DeviceList & devices, const AudioDevicePtr & device); - void checkDeviceGone(DeviceList & devices, AudioDeviceID * devIDs, const int numDevIDs, const AudioObjectPropertyScope & scope); - AudioDevicePtr createDefaultAudioDevice(const AudioObjectPropertyScope & scope); - AudioDevicePtr createAudioDevice(const AudioDeviceID & deviceID, const AudioObjectPropertyScope & scope); - bool insertAudioDevice(const AudioDevicePtr & device, const AudioObjectPropertyScope & scope); - int getChannelCount(const AudioDeviceID & deviceID, const AudioObjectPropertyScope & scope); - AudioDeviceID getDefaultDeviceID(const AudioObjectPropertyScope & scope); - DeviceFormFactor getActualFormFactor(const unsigned int sourceID); - DeviceTransport getActualTransport(const unsigned int transportType); - void fillAdditionalTypes(const AudioDeviceID & deviceID, const AudioObjectPropertyScope & scope, AudioDevicePtr device); - - static OSStatus deviceListenerProc(AudioObjectID objectID, UInt32 numberAddresses, const AudioObjectPropertyAddress addresses[], void * clientData); - }; - } -} - -#endif diff --git a/webrtc-jni/src/main/cpp/include/media/audio/windows/WindowsAudioDeviceManager.h b/webrtc-jni/src/main/cpp/include/media/audio/windows/WindowsAudioDeviceManager.h deleted file mode 100644 index 1e8fcbb..0000000 --- a/webrtc-jni/src/main/cpp/include/media/audio/windows/WindowsAudioDeviceManager.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_MF_AUDIO_DEVICE_MANAGER_H_ -#define JNI_WEBRTC_MEDIA_MF_AUDIO_DEVICE_MANAGER_H_ - -#include -#include "media/audio/AudioDeviceManager.h" -#include "platform/windows/ComPtr.h" -#include "platform/windows/ComInitializer.h" -#include "platform/windows/MFInitializer.h" -#include "mmdeviceapi.h" - -namespace jni -{ - namespace avdev - { - class WindowsAudioDeviceManager : public AudioDeviceManager, IMMNotificationClient - { - public: - WindowsAudioDeviceManager(); - ~WindowsAudioDeviceManager(); - - std::set getAudioCaptureDevices() override; - std::set getAudioPlaybackDevices() override; - - AudioDevicePtr getDefaultAudioCaptureDevice() override; - AudioDevicePtr getDefaultAudioPlaybackDevice() override; - - private: - void enumerateDevices(EDataFlow dataFlow); - void addDevice(LPCWSTR deviceId); - void removeDevice(LPCWSTR deviceId); - AudioDevicePtr createDefaultAudioDevice(const EDataFlow & dataFlow); - AudioDevicePtr createAudioDevice(LPCWSTR deviceId, EDataFlow * dataFlow); - bool insertAudioDevice(AudioDevicePtr device, EDataFlow dataFlow); - void removeAudioDevice(DeviceList & devices, std::string id, EDataFlow dataFlow); - DeviceFormFactor getActualFormFactor(EndpointFormFactor formFactor); - DeviceTransport getActualTransport(EndpointFormFactor formFactor); - void fillAdditionalTypes(AudioDevicePtr device); - - // IMMNotificationClient implementation. - STDMETHOD_(ULONG, AddRef)(); - STDMETHOD_(ULONG, Release)(); - STDMETHOD(QueryInterface)(REFIID iid, void ** object); - STDMETHOD(OnDefaultDeviceChanged) (EDataFlow flow, ERole role, LPCWSTR deviceId); - STDMETHOD(OnDeviceAdded) (LPCWSTR deviceId); - STDMETHOD(OnDeviceRemoved) (LPCWSTR deviceId); - STDMETHOD(OnDeviceStateChanged) (LPCWSTR deviceId, DWORD newState); - STDMETHOD(OnPropertyValueChanged) (LPCWSTR /*deviceId*/, const PROPERTYKEY /*key*/); - - ComInitializer comInitializer; - MFInitializer initializer; - ComPtr deviceEnumerator; - }; - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/video/CustomVideoSource.h b/webrtc-jni/src/main/cpp/include/media/video/CustomVideoSource.h deleted file mode 100644 index e6d923e..0000000 --- a/webrtc-jni/src/main/cpp/include/media/video/CustomVideoSource.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_VIDEO_CUSTOM_VIDEO_SOURCE_H_ -#define JNI_WEBRTC_MEDIA_VIDEO_CUSTOM_VIDEO_SOURCE_H_ - -#include "api/video/video_frame.h" -#include "api/video/video_source_interface.h" -#include "media/base/adapted_video_track_source.h" -#include "rtc_base/ref_counted_object.h" - -#include "media/SyncClock.h" - -#include - -namespace jni -{ - class CustomVideoSource : public webrtc::AdaptedVideoTrackSource - { - public: - explicit CustomVideoSource(std::shared_ptr clock); - - // AdaptedVideoTrackSource implementation. - virtual bool is_screencast() const override; - virtual std::optional needs_denoising() const override; - SourceState state() const override; - bool remote() const override; - - void PushFrame(const webrtc::VideoFrame & frame); - - private: - std::shared_ptr clock_; - uint16_t frame_id_; - }; -} -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/video/RawVideoFileSink.h b/webrtc-jni/src/main/cpp/include/media/video/RawVideoFileSink.h deleted file mode 100644 index 0957e30..0000000 --- a/webrtc-jni/src/main/cpp/include/media/video/RawVideoFileSink.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_RAW_VIDEO_FILE_SINK_H_ -#define JNI_WEBRTC_MEDIA_RAW_VIDEO_FILE_SINK_H_ - -#include "VideoSink.h" - -#include -#include -#include - -namespace jni -{ - class RawVideoFileSink : public VideoSink - { - public: - RawVideoFileSink(std::string fileName); - ~RawVideoFileSink(); - - void OnFrame(const webrtc::VideoFrame & frame) override; - void OnDiscardedFrame() override; - - private: - std::ofstream outputStream; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/video/VideoCapture.h b/webrtc-jni/src/main/cpp/include/media/video/VideoCapture.h deleted file mode 100644 index 66929aa..0000000 --- a/webrtc-jni/src/main/cpp/include/media/video/VideoCapture.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_VIDEO_CAPTURE_H_ -#define JNI_WEBRTC_MEDIA_VIDEO_CAPTURE_H_ - -#include "media/video/VideoCaptureBase.h" - -#include "modules/video_capture/video_capture.h" -#include "modules/video_capture/video_capture_defines.h" - -namespace jni -{ - class VideoCapture : public VideoCaptureBase - { - public: - VideoCapture(); - ~VideoCapture(); - - void start() override; - void stop() override; - void destroy() override; - - private: - webrtc::scoped_refptr captureModule; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/video/VideoCaptureBase.h b/webrtc-jni/src/main/cpp/include/media/video/VideoCaptureBase.h deleted file mode 100644 index ae171b0..0000000 --- a/webrtc-jni/src/main/cpp/include/media/video/VideoCaptureBase.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_VIDEO_CAPTURE_BASE_H_ -#define JNI_WEBRTC_MEDIA_VIDEO_CAPTURE_BASE_H_ - -#include "media/video/VideoDevice.h" - -#include "api/video/video_sink_interface.h" -#include "modules/video_capture/video_capture_defines.h" - -namespace jni -{ - class VideoCaptureBase - { - public: - VideoCaptureBase(); - ~VideoCaptureBase(); - - void setDevice(const avdev::DevicePtr & device); - void setVideoCaptureCapability(const webrtc::VideoCaptureCapability & capability); - void setVideoSink(std::unique_ptr> sink); - - virtual void start() = 0; - virtual void stop() = 0; - virtual void destroy() = 0; - - protected: - avdev::DevicePtr device; - webrtc::VideoCaptureCapability capability; - std::unique_ptr> sink; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/video/VideoCaptureCapability.h b/webrtc-jni/src/main/cpp/include/media/video/VideoCaptureCapability.h deleted file mode 100644 index 2c17332..0000000 --- a/webrtc-jni/src/main/cpp/include/media/video/VideoCaptureCapability.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_VIDEO_CAPTURE_CAPABILITY_H_ -#define JNI_WEBRTC_MEDIA_VIDEO_CAPTURE_CAPABILITY_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include - -#include "modules/video_capture/video_capture_defines.h" - -namespace jni -{ - namespace avdev - { - class VideoCaptureCapability : public webrtc::VideoCaptureCapability - { - public: - bool operator<(const VideoCaptureCapability & other) const; - }; - } - - namespace VideoCaptureCapability - { - class JavaVideoCaptureCapabilityClass : public JavaClass - { - public: - explicit JavaVideoCaptureCapabilityClass(JNIEnv * env); - - jclass cls; - jmethodID ctor; - }; - - JavaLocalRef toJava(JNIEnv * env, const avdev::VideoCaptureCapability & capability); - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/video/VideoDevice.h b/webrtc-jni/src/main/cpp/include/media/video/VideoDevice.h deleted file mode 100644 index 10bf3cf..0000000 --- a/webrtc-jni/src/main/cpp/include/media/video/VideoDevice.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_VIDEO_DEVICE_H_ -#define JNI_WEBRTC_MEDIA_VIDEO_DEVICE_H_ - -#include "media/Device.h" -#include "JavaClass.h" -#include "JavaRef.h" - -#include - -namespace jni -{ - namespace avdev - { - class VideoDevice : public Device - { - public: - VideoDevice(std::string name, std::string descriptor); - virtual ~VideoDevice() {}; - }; - - - using VideoDevicePtr = std::shared_ptr; - } - - namespace VideoDevice - { - class JavaVideoDeviceClass : public JavaClass - { - public: - explicit JavaVideoDeviceClass(JNIEnv * env); - - jclass cls; - jmethodID ctor; - jfieldID name; - jfieldID descriptor; - }; - - JavaLocalRef toJavaVideoDevice(JNIEnv * env, const avdev::VideoDevice & device); - avdev::VideoDevice toNativeVideoDevice(JNIEnv * env, const JavaRef & javaType); - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/video/VideoDeviceManager.h b/webrtc-jni/src/main/cpp/include/media/video/VideoDeviceManager.h deleted file mode 100644 index 95d92ad..0000000 --- a/webrtc-jni/src/main/cpp/include/media/video/VideoDeviceManager.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_VIDEO_DEVICE_MANAGER_H_ -#define JNI_WEBRTC_MEDIA_VIDEO_DEVICE_MANAGER_H_ - -#include "media/DeviceManager.h" -#include "media/DeviceList.h" -#include "media/video/VideoDevice.h" -#include "media/video/VideoCaptureCapability.h" - -#include "modules/video_capture/video_capture_defines.h" - -#include -#include - -namespace jni -{ - namespace avdev - { - using VideoDevicePtr = std::shared_ptr; - - - class VideoDeviceManager : public DeviceManager - { - public: - VideoDeviceManager(); - virtual ~VideoDeviceManager() {}; - - VideoDevicePtr getDefaultVideoCaptureDevice(); - - virtual std::set getVideoCaptureDevices() = 0; - virtual std::set getVideoCaptureCapabilities(const VideoDevice & device) = 0; - - protected: - void setDefaultCaptureDevice(VideoDevicePtr device); - VideoDevicePtr getDefaultCaptureDevice(); - - protected: - DeviceList captureDevices; - - private: - VideoDevicePtr defaultCaptureDevice; - std::mutex mutex; - }; - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/video/VideoSink.h b/webrtc-jni/src/main/cpp/include/media/video/VideoSink.h deleted file mode 100644 index b525168..0000000 --- a/webrtc-jni/src/main/cpp/include/media/video/VideoSink.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_VIDEO_SINK_H_ -#define JNI_WEBRTC_MEDIA_VIDEO_SINK_H_ - -#include "api/video/video_sink_interface.h" -#include "api/video/video_frame.h" - -namespace jni -{ - class VideoSink : public webrtc::VideoSinkInterface - { - public: - virtual ~VideoSink() {}; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/video/VideoTrackDesktopSource.h b/webrtc-jni/src/main/cpp/include/media/video/VideoTrackDesktopSource.h deleted file mode 100644 index 06b8a42..0000000 --- a/webrtc-jni/src/main/cpp/include/media/video/VideoTrackDesktopSource.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_VIDEO_TRACK_DESKTOP_SOURCE_H_ -#define JNI_WEBRTC_MEDIA_VIDEO_TRACK_DESKTOP_SOURCE_H_ - -#include "api/video/i420_buffer.h" -#include "media/base/adapted_video_track_source.h" -#include "modules/desktop_capture/desktop_capturer.h" -#include "rtc_base/platform_thread.h" - -namespace jni -{ - class VideoTrackDesktopSource : public webrtc::AdaptedVideoTrackSource, public webrtc::DesktopCapturer::Callback - { - public: - VideoTrackDesktopSource(); - ~VideoTrackDesktopSource(); - - void setSourceId(webrtc::DesktopCapturer::SourceId source, bool isWindow); - void setFrameRate(const uint16_t frameRate); - void setMaxFrameSize(webrtc::DesktopSize size); - void setFocusSelectedSource(bool focus); - - void start(); - void stop(); - void terminate(); - - // AdaptedVideoTrackSource implementation. - virtual bool is_screencast() const override; - virtual std::optional needs_denoising() const override; - SourceState state() const override; - bool remote() const override; - - // DesktopCapturer::Callback implementation. - void OnCaptureResult(webrtc::DesktopCapturer::Result result, std::unique_ptr frame) override; - - private: - void capture(); - void process(std::unique_ptr& frame); - - private: - uint16_t frameRate; - bool isCapturing; - bool focusSelectedSource; - - webrtc::DesktopSize maxFrameSize; - - webrtc::MediaSourceInterface::SourceState sourceState; - - webrtc::DesktopCapturer::SourceId sourceId; - bool sourceIsWindow; - - std::unique_ptr lastFrame; - - webrtc::PlatformThread captureThread; - - webrtc::scoped_refptr buffer; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/video/VideoTrackDeviceSource.h b/webrtc-jni/src/main/cpp/include/media/video/VideoTrackDeviceSource.h deleted file mode 100644 index 17b5893..0000000 --- a/webrtc-jni/src/main/cpp/include/media/video/VideoTrackDeviceSource.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_VIDEO_TRACK_DEVICE_SOURCE_H_ -#define JNI_WEBRTC_MEDIA_VIDEO_TRACK_DEVICE_SOURCE_H_ - -#include "api/create_peerconnection_factory.h" -#include "api/video/video_frame.h" -#include "api/video/video_sink_interface.h" -#include "pc/video_track_source.h" -#include "media/base/video_adapter.h" -#include "media/base/video_broadcaster.h" -#include "modules/video_capture/video_capture.h" -#include "modules/video_capture/video_capture_defines.h" - -#include "media/video/VideoTrackDeviceSourceBase.h" -#include "media/video/VideoDevice.h" - -namespace jni -{ - class VideoTrackDeviceSource : public webrtc::VideoTrackSource, public webrtc::VideoSinkInterface, public VideoTrackDeviceSourceBase - { - public: - VideoTrackDeviceSource(); - ~VideoTrackDeviceSource(); - - // VideoTrackDeviceSourceBase implementation. - void start() override; - void stop() override; - - // VideoSourceInterface implementation. - void AddOrUpdateSink(webrtc::VideoSinkInterface * sink, const webrtc::VideoSinkWants & wants) override; - void RemoveSink(webrtc::VideoSinkInterface * sink) override; - - // VideoTrackSource implementation. - webrtc::VideoSourceInterface * source() override; - - // VideoSinkInterface implementation. - void OnFrame(const webrtc::VideoFrame & frame) override; - - private: - bool startCapture(); - void updateVideoAdapter(); - void destroy(); - - private: - webrtc::scoped_refptr captureModule; - webrtc::VideoBroadcaster broadcaster; - webrtc::VideoAdapter videoAdapter; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/video/VideoTrackDeviceSourceBase.h b/webrtc-jni/src/main/cpp/include/media/video/VideoTrackDeviceSourceBase.h deleted file mode 100644 index 91789db..0000000 --- a/webrtc-jni/src/main/cpp/include/media/video/VideoTrackDeviceSourceBase.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_VIDEO_TRACK_DEVICE_SOURCE_BASE_H_ -#define JNI_WEBRTC_MEDIA_VIDEO_TRACK_DEVICE_SOURCE_BASE_H_ - -#include "modules/video_capture/video_capture_defines.h" - -#include "media/video/VideoDevice.h" - -namespace jni -{ - class VideoTrackDeviceSourceBase - { - public: - VideoTrackDeviceSourceBase(); - ~VideoTrackDeviceSourceBase(); - - void setVideoDevice(const avdev::VideoDevicePtr & device); - void setVideoCaptureCapability(const webrtc::VideoCaptureCapability & capability); - - virtual void start() = 0; - virtual void stop() = 0; - - protected: - avdev::VideoDevicePtr device; - webrtc::VideoCaptureCapability capability; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/video/desktop/DesktopCaptureCallback.h b/webrtc-jni/src/main/cpp/include/media/video/desktop/DesktopCaptureCallback.h deleted file mode 100644 index e817114..0000000 --- a/webrtc-jni/src/main/cpp/include/media/video/desktop/DesktopCaptureCallback.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_DESKTOP_CAPTURE_CALLBACK_H_ -#define JNI_WEBRTC_MEDIA_DESKTOP_CAPTURE_CALLBACK_H_ - -#include "api/VideoFrame.h" -#include "JavaClass.h" -#include "JavaRef.h" - -#include "api/video/i420_buffer.h" -#include "modules/desktop_capture/desktop_capturer.h" - -#include - -namespace jni -{ - class DesktopCaptureCallback : public webrtc::DesktopCapturer::Callback - { - public: - DesktopCaptureCallback(JNIEnv * env, const JavaGlobalRef & callback); - ~DesktopCaptureCallback() override = default; - - // DesktopCapturer::Callback implementation. - void OnCaptureResult(webrtc::DesktopCapturer::Result result, std::unique_ptr frame) override; - - private: - class JavaDesktopCaptureCallbackClass : public JavaClass - { - public: - explicit JavaDesktopCaptureCallbackClass(JNIEnv * env); - - jmethodID onCaptureResult; - }; - - private: - JavaGlobalRef callback; - - const std::shared_ptr javaClass; - const std::shared_ptr javaFrameClass; - - webrtc::scoped_refptr i420Buffer; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/video/desktop/DesktopCapturer.h b/webrtc-jni/src/main/cpp/include/media/video/desktop/DesktopCapturer.h deleted file mode 100644 index 06a4c2a..0000000 --- a/webrtc-jni/src/main/cpp/include/media/video/desktop/DesktopCapturer.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_DESKTOP_CAPTURER_H_ -#define JNI_WEBRTC_MEDIA_DESKTOP_CAPTURER_H_ - -#if defined(WEBRTC_WIN) -#include "platform/windows/ComInitializer.h" -#endif - -#include "modules/desktop_capture/desktop_capturer.h" - -#include -#include - -namespace jni -{ - class DesktopCapturer - { - public: - explicit DesktopCapturer(bool screenCapturer); - ~DesktopCapturer(); - - // webrtc::DesktopCapturer implementations. - void Start(webrtc::DesktopCapturer::Callback * callback); - void SetMaxFrameRate(uint32_t max_frame_rate); - void SetSharedMemoryFactory(std::unique_ptr factory); - void CaptureFrame(); - void SetExcludedWindow(webrtc::WindowId window); - bool GetSourceList(webrtc::DesktopCapturer::SourceList * sources); - bool SelectSource(webrtc::DesktopCapturer::SourceId id); - bool FocusOnSelectedSource(); - void setFocusSelectedSource(bool focus); - bool IsOccluded(const webrtc::DesktopVector & pos); - - protected: - std::unique_ptr capturer; - - bool focusSelectedSource; - -#if defined(WEBRTC_WIN) - private: - ComInitializer comInitializer; -#endif - }; -} - -#endif diff --git a/webrtc-jni/src/main/cpp/include/media/video/desktop/DesktopFrame.h b/webrtc-jni/src/main/cpp/include/media/video/desktop/DesktopFrame.h deleted file mode 100644 index bfa0f3f..0000000 --- a/webrtc-jni/src/main/cpp/include/media/video/desktop/DesktopFrame.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_DESKTOP_FRAME_H_ -#define JNI_WEBRTC_MEDIA_DESKTOP_FRAME_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include "modules/desktop_capture/desktop_frame.h" - -#include -#include - -namespace jni -{ - namespace DesktopFrame - { - class JavaDesktopFrameClass : public JavaClass - { - public: - explicit JavaDesktopFrameClass(JNIEnv * env); - - jclass cls; - jmethodID ctor; - }; - - JavaLocalRef toJava(JNIEnv * env, const webrtc::DesktopFrame * frame); - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/video/desktop/DesktopSource.h b/webrtc-jni/src/main/cpp/include/media/video/desktop/DesktopSource.h deleted file mode 100644 index 7bfb3df..0000000 --- a/webrtc-jni/src/main/cpp/include/media/video/desktop/DesktopSource.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_DESKTOP_SOURCE_H_ -#define JNI_WEBRTC_MEDIA_DESKTOP_SOURCE_H_ - -#include "JavaClass.h" -#include "JavaRef.h" - -#include "modules/desktop_capture/desktop_capturer.h" - -#include - -namespace jni -{ - namespace DesktopSource - { - class JavaDesktopSourceClass : public JavaClass - { - public: - explicit JavaDesktopSourceClass(JNIEnv * env); - - jclass cls; - jmethodID ctor; - jfieldID id; - jfieldID title; - }; - - JavaLocalRef toJava(JNIEnv * env, const webrtc::DesktopCapturer::Source & source); - - webrtc::DesktopCapturer::Source toNative(JNIEnv * env, const JavaRef & javaType); - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/video/desktop/PowerManagement.h b/webrtc-jni/src/main/cpp/include/media/video/desktop/PowerManagement.h deleted file mode 100644 index b5e8e74..0000000 --- a/webrtc-jni/src/main/cpp/include/media/video/desktop/PowerManagement.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_DESKTOP_POWER_MANAGEMENT_H_ -#define JNI_WEBRTC_MEDIA_DESKTOP_POWER_MANAGEMENT_H_ - -namespace jni -{ - namespace avdev - { - class PowerManagement - { - public: - PowerManagement() = default; - virtual ~PowerManagement() = default; - - virtual void enableUserActivity() = 0; - virtual void disableUserActivity() = 0; - }; - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/video/desktop/linux/LinuxPowerManagement.h b/webrtc-jni/src/main/cpp/include/media/video/desktop/linux/LinuxPowerManagement.h deleted file mode 100644 index e01b92f..0000000 --- a/webrtc-jni/src/main/cpp/include/media/video/desktop/linux/LinuxPowerManagement.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_DESKTOP_LINUX_POWER_MANAGEMENT_H_ -#define JNI_WEBRTC_MEDIA_DESKTOP_LINUX_POWER_MANAGEMENT_H_ - -#include "media/video/desktop/PowerManagement.h" - -#include - -namespace jni -{ - namespace avdev - { - class LinuxPowerManagement : public PowerManagement - { - public: - LinuxPowerManagement(); - ~LinuxPowerManagement() = default; - - void enableUserActivity(); - void disableUserActivity(); - - private: - uint32_t dbusCookie = 0; - - // KDE >= 4 and GNOME >= 3.10 - const char * BUS_SERVICE_NAME = "org.freedesktop.ScreenSaver"; - const char * BUS_SERVICE_PATH = "/org/freedesktop/ScreenSaver"; - const char * BUS_INTERFACE = "org.freedesktop.ScreenSaver"; - - const char * appName = "WebRTC - Java"; - const char * reason = "Running WebRTC"; - }; - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/video/desktop/macos/MacOSPowerManagement.h b/webrtc-jni/src/main/cpp/include/media/video/desktop/macos/MacOSPowerManagement.h deleted file mode 100644 index 87b69ea..0000000 --- a/webrtc-jni/src/main/cpp/include/media/video/desktop/macos/MacOSPowerManagement.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_DESKTOP_MACOS_POWER_MANAGEMENT_H_ -#define JNI_WEBRTC_MEDIA_DESKTOP_MACOS_POWER_MANAGEMENT_H_ - -#include "media/video/desktop/PowerManagement.h" - -#include - -namespace jni -{ - namespace avdev - { - class MacOSPowerManagement : public PowerManagement - { - public: - MacOSPowerManagement(); - ~MacOSPowerManagement() = default; - - void enableUserActivity(); - void disableUserActivity(); - - private: - IOPMAssertionID powerAssertion; - }; - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/video/desktop/windows/WindowsPowerManagement.h b/webrtc-jni/src/main/cpp/include/media/video/desktop/windows/WindowsPowerManagement.h deleted file mode 100644 index d192984..0000000 --- a/webrtc-jni/src/main/cpp/include/media/video/desktop/windows/WindowsPowerManagement.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_DESKTOP_WIN_POWER_MANAGEMENT_H_ -#define JNI_WEBRTC_MEDIA_DESKTOP_WIN_POWER_MANAGEMENT_H_ - -#include "media/video/desktop/PowerManagement.h" - -namespace jni -{ - namespace avdev - { - class WindowsPowerManagement : public PowerManagement - { - public: - WindowsPowerManagement(); - ~WindowsPowerManagement() = default; - - void enableUserActivity(); - void disableUserActivity(); - }; - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/video/linux/V4l2VideoDeviceManager.h b/webrtc-jni/src/main/cpp/include/media/video/linux/V4l2VideoDeviceManager.h deleted file mode 100644 index 454a386..0000000 --- a/webrtc-jni/src/main/cpp/include/media/video/linux/V4l2VideoDeviceManager.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_V4L2_VIDEO_DEVICE_MANAGER_H_ -#define JNI_WEBRTC_MEDIA_V4L2_VIDEO_DEVICE_MANAGER_H_ - -#include "media/video/VideoDeviceManager.h" - -#include -#include -#include - -namespace jni -{ - namespace avdev - { - class V4l2VideoDeviceManager : public VideoDeviceManager - { - public: - V4l2VideoDeviceManager(); - ~V4l2VideoDeviceManager(); - - std::set getVideoCaptureDevices() override; - std::set getVideoCaptureCapabilities(const VideoDevice & device) override; - - private: - void addDevice(const std::string & name, const std::string & descriptor); - void removeDevice(const std::string & name, const std::string & descriptor); - void run(); - bool checkDevice(const std::string & descriptor); - int ioctlDevice(int fh, int request, void * arg); - webrtc::VideoType toVideoType(const std::uint32_t & v4l2MediaType); - - struct MediaFormatConfiguration { - std::uint32_t v4l2MediaType; - webrtc::VideoType videoType; - }; - - private: - std::thread thread; - std::atomic running; - struct udev * udev; - }; - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/video/macos/AVFVideoDeviceManager.h b/webrtc-jni/src/main/cpp/include/media/video/macos/AVFVideoDeviceManager.h deleted file mode 100644 index bbd2f10..0000000 --- a/webrtc-jni/src/main/cpp/include/media/video/macos/AVFVideoDeviceManager.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_AVF_VIDEO_DEVICE_MANAGER_H_ -#define JNI_WEBRTC_MEDIA_AVF_VIDEO_DEVICE_MANAGER_H_ - -#include "media/video/VideoDeviceManager.h" - -#include - -namespace jni -{ - namespace avdev - { - class AVFVideoDeviceManager : public VideoDeviceManager - { - public: - AVFVideoDeviceManager(); - ~AVFVideoDeviceManager(); - - std::set getVideoCaptureDevices() override; - std::set getVideoCaptureCapabilities(const VideoDevice & device) override; - - private: - void insertDevice(AVCaptureDevice * device, bool notify); - void removeDevice(AVCaptureDevice * device, bool notify); - - void onDeviceConnected(AVCaptureDevice * device); - void onDeviceDisconnected(AVCaptureDevice * device); - - webrtc::VideoType toVideoType(const std::uint32_t & fourCC); - - private: - id devConnectObserver; - id devDisconnectObserver; - }; - } -} - -#endif diff --git a/webrtc-jni/src/main/cpp/include/media/video/macos/VideoCaptureMac.h b/webrtc-jni/src/main/cpp/include/media/video/macos/VideoCaptureMac.h deleted file mode 100644 index 0cce911..0000000 --- a/webrtc-jni/src/main/cpp/include/media/video/macos/VideoCaptureMac.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_VIDEO_CAPTURE_MAC_H_ -#define JNI_WEBRTC_MEDIA_VIDEO_CAPTURE_MAC_H_ - -#include "media/video/VideoCaptureBase.h" - -#include "rtc_base/timestamp_aligner.h" - -#include "sdk/objc/base/RTCVideoCapturer.h" -#include "sdk/objc/base/RTCMacros.h" -#include "sdk/objc/components/capturer/RTCCameraVideoCapturer.h" - - -@interface VideoCaptureCallback - : NSObject -@end - - -namespace jni -{ - class VideoCaptureMac : public VideoCaptureBase - { - public: - VideoCaptureMac(); - ~VideoCaptureMac(); - - void start() override; - void stop() override; - void destroy() override; - - void OnCapturedFrame(RTC_OBJC_TYPE(RTCVideoFrame) * frame); - - private: - webrtc::TimestampAligner timestamp_aligner; - RTCCameraVideoCapturer * cameraVideoCapturer; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/video/macos/VideoTrackDeviceSourceMac.h b/webrtc-jni/src/main/cpp/include/media/video/macos/VideoTrackDeviceSourceMac.h deleted file mode 100644 index 899faec..0000000 --- a/webrtc-jni/src/main/cpp/include/media/video/macos/VideoTrackDeviceSourceMac.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_VIDEO_TRACK_DEVICE_SOURCE_MAC_H_ -#define JNI_WEBRTC_MEDIA_VIDEO_TRACK_DEVICE_SOURCE_MAC_H_ - -#include "media/base/adapted_video_track_source.h" -#include "modules/video_capture/video_capture_defines.h" -#include "rtc_base/timestamp_aligner.h" - -#include "sdk/objc/base/RTCVideoCapturer.h" -#include "sdk/objc/base/RTCMacros.h" -#include "sdk/objc/components/capturer/RTCCameraVideoCapturer.h" - -#include "media/video/VideoTrackDeviceSourceBase.h" - - -@interface VideoTrackDeviceSourceCallback - : NSObject -@end - - -namespace jni -{ - class VideoTrackDeviceSourceMac : public webrtc::AdaptedVideoTrackSource, public VideoTrackDeviceSourceBase - { - public: - VideoTrackDeviceSourceMac(); - ~VideoTrackDeviceSourceMac(); - - // VideoTrackDeviceSourceBase implementation. - void start() override; - void stop() override; - - // AdaptedVideoTrackSource implementation. - virtual bool is_screencast() const override; - virtual std::optional needs_denoising() const override; - SourceState state() const override; - bool remote() const override; - - void OnCapturedFrame(RTC_OBJC_TYPE(RTCVideoFrame) * frame); - - private: - void destroy(); - - private: - webrtc::TimestampAligner timestamp_aligner; - - RTCCameraVideoCapturer * cameraVideoCapturer; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/media/video/windows/WindowsVideoDeviceManager.h b/webrtc-jni/src/main/cpp/include/media/video/windows/WindowsVideoDeviceManager.h deleted file mode 100644 index f195fd7..0000000 --- a/webrtc-jni/src/main/cpp/include/media/video/windows/WindowsVideoDeviceManager.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_MEDIA_MF_VIDEO_DEVICE_MANAGER_H_ -#define JNI_WEBRTC_MEDIA_MF_VIDEO_DEVICE_MANAGER_H_ - -#include "media/video/VideoDeviceManager.h" -#include "platform/windows/WinHotplugNotifier.h" - -namespace jni -{ - namespace avdev - { - class WindowsVideoDeviceManager : public VideoDeviceManager, WinHotplugNotifier - { - public: - WindowsVideoDeviceManager(); - ~WindowsVideoDeviceManager() = default; - - std::set getVideoCaptureDevices() override; - std::set getVideoCaptureCapabilities(const VideoDevice & device) override; - - protected: - void onDeviceConnected(std::wstring symLink) override; - void onDeviceDisconnected(std::wstring symLink) override; - - private: - void enumerateDevices(std::wstring * symLink); - VideoDevicePtr createVideoDevice(WCHAR * symbolicLink, WCHAR * friendlyName); - - bool insertVideoDevice(VideoDevicePtr device); - }; - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/platform/macos/MacUtils.h b/webrtc-jni/src/main/cpp/include/platform/macos/MacUtils.h deleted file mode 100644 index 4bf59b2..0000000 --- a/webrtc-jni/src/main/cpp/include/platform/macos/MacUtils.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_MACOS_MAC_UTILS_H_ -#define JNI_MACOS_MAC_UTILS_H_ - -#include "Exception.h" - -#include - -#import - - -inline void ThrowIfFailed(OSStatus status, const char * msg, ...) -{ - if (status != noErr) { - char message[256]; - - va_list args; - va_start(args, msg); - vsnprintf(message, 256, msg, args); - va_end(args); - - throw jni::Exception("%s Status: %d", message, status); - } -} - -namespace jni -{ - const std::string CFStringRefToUTF8(CFStringRef stringRef); -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/platform/windows/ComInitializer.h b/webrtc-jni/src/main/cpp/include/platform/windows/ComInitializer.h deleted file mode 100644 index 136be9d..0000000 --- a/webrtc-jni/src/main/cpp/include/platform/windows/ComInitializer.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WINDOWS_COM_INITIALIZER_H_ -#define JNI_WINDOWS_COM_INITIALIZER_H_ - -namespace jni -{ - class ComInitializer - { - public: - ComInitializer(); - virtual ~ComInitializer(); - - bool isInitialized(); - - private: - bool initialized; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/platform/windows/ComPtr.h b/webrtc-jni/src/main/cpp/include/platform/windows/ComPtr.h deleted file mode 100644 index 1c110f9..0000000 --- a/webrtc-jni/src/main/cpp/include/platform/windows/ComPtr.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WINDOWS_COM_PTR_H_ -#define JNI_WINDOWS_COM_PTR_H_ - -#include - -namespace jni -{ - template - class ComPtr - { - public: - ComPtr() : ptr(nullptr) - { - } - - ComPtr(Interface * p) : ptr(p) - { - if (p != nullptr) { - ptr->AddRef(); - } - } - - ComPtr(const ComPtr & refComPtr) : ptr(refComPtr.ptr) - { - if (ptr) { - ptr->AddRef(); - } - } - - ~ComPtr() - { - Release(); - } - - public: - operator Interface*() const - { - return ptr; - } - - bool operator!() const - { - return (ptr == nullptr); - } - - Interface ** operator&() - { - return &ptr; - } - - Interface & operator*() const - { - return *ptr; - } - - bool operator<(Interface * p) const - { - return ptr < p; - } - - bool operator!=(Interface * p) const - { - return !operator==(p); - } - - bool operator==(Interface * p) const - { - return ptr == p; - } - - Interface * operator->() const - { - return ptr; - } - - void Attach(Interface * p) - { - if (p) { - Release(); - ptr = p; - } - } - - Interface * Detach() - { - Interface * copy = ptr; - ptr = nullptr; - return copy; - } - - void Release() - { - if (ptr) { - ptr->Release(); - ptr = nullptr; - } - } - - template - HRESULT QueryInterface(Query ** interfacePtr) - { - return ptr->QueryInterface(interfacePtr); - } - - HRESULT QueryInterface(const IID & iid, void ** object) { - return ptr->QueryInterface(iid, object); - } - - BOOL IsEqualObject(IUnknown * other) - { - if (!ptr || !other) - return false; - - if (!ptr && !other) - return true; - - IUnknown * mid = nullptr; - ptr->QueryInterface(IID_IUnknown, (void**)&mid); - - IUnknown * oid = nullptr; - other->QueryInterface(IID_IUnknown, (void**)&oid); - - BOOL equal = static_cast(mid) == static_cast(oid); - - mid->Release(); - oid->Release(); - - return equal; - } - - private: - Interface * ptr; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/platform/windows/MFInitializer.h b/webrtc-jni/src/main/cpp/include/platform/windows/MFInitializer.h deleted file mode 100644 index 5305796..0000000 --- a/webrtc-jni/src/main/cpp/include/platform/windows/MFInitializer.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WINDOWS_MF_INITIALIZER_H_ -#define JNI_WINDOWS_MF_INITIALIZER_H_ - -#include - -namespace jni -{ - class MFInitializer - { - public: - MFInitializer(); - virtual ~MFInitializer(); - - bool isInitialized(); - - private: - bool initialized; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/platform/windows/MFUtils.h b/webrtc-jni/src/main/cpp/include/platform/windows/MFUtils.h deleted file mode 100644 index 2eecfb9..0000000 --- a/webrtc-jni/src/main/cpp/include/platform/windows/MFUtils.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WINDOWS_MF_UTILS_H_ -#define JNI_WINDOWS_MF_UTILS_H_ - -#include -#include - -#include "common_video/libyuv/include/webrtc_libyuv.h" - -namespace jni -{ - namespace mf - { - struct MediaFormatConfiguration { - GUID mfMediaType; - webrtc::VideoType videoType; - }; - - const void CreateMediaSource(GUID mediaType, std::string symlink, IMFMediaSource ** source); - - const webrtc::VideoType toVideoType(const GUID & mfMediaType); - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/platform/windows/WinHotplugNotifier.h b/webrtc-jni/src/main/cpp/include/platform/windows/WinHotplugNotifier.h deleted file mode 100644 index 213d5d9..0000000 --- a/webrtc-jni/src/main/cpp/include/platform/windows/WinHotplugNotifier.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WINDOWS_HOTPLUG_NOTIFIER_H_ -#define JNI_WINDOWS_HOTPLUG_NOTIFIER_H_ - -#include -#include -#include -#include - -namespace jni -{ - class WinHotplugNotifier - { - public: - WinHotplugNotifier(std::list devInterfaces); - virtual ~WinHotplugNotifier(); - - WinHotplugNotifier(WinHotplugNotifier const &) = delete; - void operator=(WinHotplugNotifier const &) = delete; - - protected: - void start(); - void stop(); - - virtual void onDeviceConnected(std::wstring symLink) = 0; - virtual void onDeviceDisconnected(std::wstring symLink) = 0; - - private: - bool initializeWindow(); - bool registerForDeviceNotification(); - - static void onClose(HWND hWnd); - static void onDeviceChange(HWND hWnd, WPARAM wParam, LPARAM lParam); - static LRESULT CALLBACK wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); - - static DWORD WINAPI run(void * context); - - std::list deviceInterfaces; - std::list deviceNotifyHandles; - - HWND hWnd; - HANDLE threadHandle; - - const CHAR * CLASS_NAME = "MMF Device Notification Class"; - const CHAR * WINDOW_NAME = "MMF Device Notification Application"; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/include/platform/windows/WinUtils.h b/webrtc-jni/src/main/cpp/include/platform/windows/WinUtils.h deleted file mode 100644 index 47e87f4..0000000 --- a/webrtc-jni/src/main/cpp/include/platform/windows/WinUtils.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WINDOWS_WIN_UTILS_H_ -#define JNI_WINDOWS_WIN_UTILS_H_ - -#include "Exception.h" - -#include -#include "mmdeviceapi.h" -#include -#include -#include - - -#define THROW_IF_FAILED(hr, msg, ...) ThrowIfFailed(hr, msg, __VA_ARGS__) - - -inline std::string WideStrToStr(LPCWSTR wstr) -{ - int wslen = static_cast(wcslen(wstr)); - int length = WideCharToMultiByte(CP_UTF8, 0, wstr, wslen, NULL, 0, NULL, NULL); - std::string str(length, 0); - WideCharToMultiByte(CP_UTF8, 0, wstr, wslen, &str[0], length, NULL, NULL); - - return str; -} - -inline std::wstring UTF8Decode(const std::string & str) -{ - if (str.empty()) { - return std::wstring(); - } - - int strSize = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int) str.size(), NULL, 0); - if (strSize <= 0) { - throw std::runtime_error("MultiByteToWideChar() failed: " + std::to_string(strSize)); - } - - std::wstring wstrTo(strSize, 0); - MultiByteToWideChar(CP_UTF8, 0, &str[0], (int) str.size(), &wstrTo[0], strSize); - - return wstrTo; -} - -inline std::string UTF8Encode(const std::wstring & wstr) -{ - if (wstr.empty()) { - return std::string(); - } - - int strSize = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int) wstr.size(), NULL, 0, NULL, NULL); - if (strSize <= 0) { - throw std::runtime_error("WideCharToMultiByte() failed: " + std::to_string(strSize)); - } - - std::string str(strSize, 0); - WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int) wstr.size(), &str[0], strSize, NULL, NULL); - - return str; -} - -inline void ThrowIfFailed(HRESULT hr, const char * msg, ...) { - if (FAILED(hr)) { - char message[256]; - - va_list args; - va_start(args, msg); - vsnprintf(message, 256, msg, args); - va_end(args); - - std::string comMessage = _com_error(hr).ErrorMessage(); - - throw jni::Exception("%s %s", message, comMessage.c_str()); - } -} - -inline std::string RoleToStr(ERole role) -{ - switch (role) { - case eConsole: - return "Console"; - case eMultimedia: - return "Multimedia"; - case eCommunications: - return "Communications"; - default: - return "Unknown Role"; - } -} - -inline std::string FormFactorToStr(EndpointFormFactor formFactor) -{ - switch (formFactor) { - case RemoteNetworkDevice: - return "RemoteNetworkDevice"; - case Speakers: - return "Speakers"; - case Headphones: - return "Headphones"; - case Microphone: - return "Microphone"; - case Headset: - return "Headset"; - case Handset: - return "Handset"; - case UnknownDigitalPassthrough: - return "UnknownDigitalPassthrough"; - case SPDIF: - return "SPDIF"; - case DigitalAudioDisplayDevice: - return "DigitalAudioDisplayDevice"; - case UnknownFormFactor: - return "UnknownFormFactor"; - case EndpointFormFactor_enum_count: - return "EndpointFormFactor_enum_count"; - default: - return "Unknown Form Factor"; - } -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_AudioConverter.cpp b/webrtc-jni/src/main/cpp/src/JNI_AudioConverter.cpp deleted file mode 100644 index 47e1a33..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_AudioConverter.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_AudioConverter.h" -#include "api/audio/audio_processing.h" -#include "media/audio/AudioConverter.h" -#include "JavaUtils.h" - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioConverter_convertInternal -(JNIEnv * env, jobject caller, jbyteArray src, jint nSrcSamples, jbyteArray dst, jint nDstSamples) -{ - jni::AudioConverter * converter = GetHandle(env, caller); - CHECK_HANDLE(converter); - - jboolean isDstCopy = JNI_FALSE; - - jbyte * srcPtr = env->GetByteArrayElements(src, nullptr); - jbyte * dstPtr = env->GetByteArrayElements(dst, &isDstCopy); - - converter->convert(reinterpret_cast(srcPtr), nSrcSamples, reinterpret_cast(dstPtr), nDstSamples); - - if (isDstCopy == JNI_TRUE) { - jsize dstLength = env->GetArrayLength(dst); - - env->SetByteArrayRegion(dst, 0, dstLength, dstPtr); - } - - env->ReleaseByteArrayElements(src, srcPtr, JNI_ABORT); - env->ReleaseByteArrayElements(dst, dstPtr, JNI_ABORT); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioConverter_dispose -(JNIEnv * env, jobject caller) -{ - jni::AudioConverter * converter = GetHandle(env, caller); - CHECK_HANDLE(converter); - - SetHandle(env, caller, nullptr); - - delete converter; -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioConverter_initialize -(JNIEnv * env, jobject caller, jint srcSampleRate, jint srcChannels, jint dstSampleRate, jint dstChannels) -{ - // 10 ms frames - size_t srcFrames = webrtc::AudioProcessing::GetFrameSize(srcSampleRate); - size_t dstFrames = webrtc::AudioProcessing::GetFrameSize(dstSampleRate); - - jni::AudioConverter * converter = jni::AudioConverter::create(srcFrames, srcChannels, dstFrames, dstChannels).release(); - - SetHandle(env, caller, converter); -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_AudioDeviceModule.cpp b/webrtc-jni/src/main/cpp/src/JNI_AudioDeviceModule.cpp deleted file mode 100644 index 2528d25..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_AudioDeviceModule.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_AudioDeviceModule.h" -#include "Exception.h" -#include "JavaEnums.h" -#include "JavaError.h" -#include "JavaRef.h" -#include "JavaUtils.h" -#include "WebRTCContext.h" -#include "api/audio/create_audio_device_module.h" - -#include "api/scoped_refptr.h" - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModule_initialize -(JNIEnv * env, jobject caller, jobject jAudioLayer) -{ - jni::WebRTCContext * context = static_cast(javaContext); - auto audioLayer = jni::JavaEnums::toNative(env, jAudioLayer); - - webrtc::scoped_refptr audioModule = webrtc::CreateAudioDeviceModule(context->webrtcEnv, audioLayer); - - if (!audioModule) { - env->Throw(jni::JavaError(env, "Create AudioDeviceModule failed")); - return; - } - - if (audioModule->Init() != 0) { - env->Throw(jni::JavaError(env, "Initialize AudioDeviceModule failed")); - return; - } - - SetHandle(env, caller, audioModule.release()); -} diff --git a/webrtc-jni/src/main/cpp/src/JNI_AudioDeviceModuleBase.cpp b/webrtc-jni/src/main/cpp/src/JNI_AudioDeviceModuleBase.cpp deleted file mode 100644 index 38b8256..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_AudioDeviceModuleBase.cpp +++ /dev/null @@ -1,473 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_AudioDeviceModuleBase.h" -#include "Exception.h" -#include "JavaArrayList.h" -#include "JavaEnums.h" -#include "JavaError.h" -#include "JavaObject.h" -#include "JavaRef.h" -#include "JavaString.h" -#include "JavaUtils.h" -#include "WebRTCContext.h" -#include "api/audio/create_audio_device_module.h" -#include "media/audio/AudioDevice.h" -#include "media/audio/AudioTransportSink.h" -#include "media/audio/AudioTransportSource.h" - -#include "api/scoped_refptr.h" -#include "modules/audio_device/include/audio_device.h" -#include "rtc_base/logging.h" - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_initPlayout -(JNIEnv * env, jobject caller) -{ - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLE(audioModule); - - if (audioModule->InitPlayout() != 0) { - env->Throw(jni::JavaError(env, "Init playout failed")); - return; - } -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_stopPlayout -(JNIEnv* env, jobject caller) -{ - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLE(audioModule); - - if (audioModule->StopPlayout() != 0) { - env->Throw(jni::JavaError(env, "Stop playout failed")); - return; - } -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_startPlayout -(JNIEnv* env, jobject caller) -{ - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLE(audioModule); - - if (audioModule->StartPlayout() != 0) { - env->Throw(jni::JavaError(env, "Start playout failed")); - return; - } -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_initRecording -(JNIEnv * env, jobject caller) -{ - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLE(audioModule); - - if (audioModule->InitRecording() != 0) { - env->Throw(jni::JavaError(env, "Init recording failed")); - return; - } -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_stopRecording -(JNIEnv* env, jobject caller) -{ - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLE(audioModule); - - if (audioModule->StopRecording() != 0) { - env->Throw(jni::JavaError(env, "Stop recording failed")); - return; - } -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_startRecording -(JNIEnv* env, jobject caller) -{ - webrtc::AudioDeviceModule* audioModule = GetHandle(env, caller); - CHECK_HANDLE(audioModule); - - if (audioModule->StartRecording() != 0) { - env->Throw(jni::JavaError(env, "Start recording failed")); - return; - } -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_getPlayoutDevices -(JNIEnv* env, jobject caller) -{ - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLEV(audioModule, nullptr); - - char name[webrtc::kAdmMaxDeviceNameSize]; - char guid[webrtc::kAdmMaxGuidSize]; - - int16_t deviceCount = audioModule->PlayoutDevices(); - - jni::JavaArrayList deviceList(env, deviceCount); - - for (int i = 0; i < deviceCount; ++i) { - if (audioModule->PlayoutDeviceName(i, name, guid) == 0) { - auto device = std::make_shared(name, guid); - device -> directionType = jni::avdev::AudioDeviceDirectionType::adtRender; - - deviceList.add(jni::AudioDevice::toJavaAudioDevice(env, device)); - } - } - - return deviceList.listObject().release(); -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_getRecordingDevices -(JNIEnv * env, jobject caller) -{ - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLEV(audioModule, nullptr); - - char name[webrtc::kAdmMaxDeviceNameSize]; - char guid[webrtc::kAdmMaxGuidSize]; - - int16_t deviceCount = audioModule->RecordingDevices(); - - jni::JavaArrayList deviceList(env, deviceCount); - - for (int i = 0; i < deviceCount; ++i) { - if (audioModule->RecordingDeviceName(i, name, guid) == 0) { - auto device = std::make_shared(name, guid); - device -> directionType = jni::avdev::AudioDeviceDirectionType::adtCapture; - - deviceList.add(jni::AudioDevice::toJavaAudioDevice(env, device)); - } - } - - return deviceList.listObject().release(); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_setPlayoutDevice -(JNIEnv * env, jobject caller, jobject device) -{ - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLE(audioModule); - - if (!device) { - env->Throw(jni::JavaNullPointerException(env, "AudioDevice is null")); - return; - } - - jni::JavaObject obj(env, jni::JavaLocalRef(env, device)); - - const auto javaClass = jni::JavaClasses::get(env); - const std::string devGuid = jni::JavaString::toNative(env, obj.getString(javaClass->descriptor)); - - uint16_t index = 0; - int16_t deviceCount = audioModule->PlayoutDevices(); - - char name[webrtc::kAdmMaxDeviceNameSize]; - char guid[webrtc::kAdmMaxGuidSize]; - - for (int i = 0; i < deviceCount; ++i) { - if ((audioModule->PlayoutDeviceName(i, name, guid) == 0) && devGuid == std::string(guid)) { - index = i; - break; - } - } - - if (audioModule->SetPlayoutDevice(index) != 0) { - env->Throw(jni::JavaError(env, "Set playout device failed")); - return; - } -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_setRecordingDevice -(JNIEnv * env, jobject caller, jobject device) -{ - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLE(audioModule); - - if (!device) { - env->Throw(jni::JavaNullPointerException(env, "AudioDevice is null")); - return; - } - - jni::JavaObject obj(env, jni::JavaLocalRef(env, device)); - - const auto javaClass = jni::JavaClasses::get(env); - const std::string devGuid = jni::JavaString::toNative(env, obj.getString(javaClass->descriptor)); - - uint16_t index = 0; - int16_t deviceCount = audioModule->RecordingDevices(); - - char name[webrtc::kAdmMaxDeviceNameSize]; - char guid[webrtc::kAdmMaxGuidSize]; - - for (int i = 0; i < deviceCount; ++i) { - if ((audioModule->RecordingDeviceName(i, name, guid) == 0) && devGuid == std::string(guid)) { - index = i; - break; - } - } - - if (audioModule->SetRecordingDevice(index) != 0) { - env->Throw(jni::JavaError(env, "Set recording device failed")); - return; - } -} - -JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_isSpeakerMuted -(JNIEnv * env, jobject caller) -{ - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLEV(audioModule, true); - - bool mute = true; - - audioModule->SpeakerMute(&mute); - - return mute; -} - -JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_isMicrophoneMuted -(JNIEnv * env, jobject caller) -{ - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLEV(audioModule, true); - - bool mute = true; - - audioModule->MicrophoneMute(&mute); - - return mute; -} - -JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_getSpeakerVolume -(JNIEnv * env, jobject caller) -{ - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLEV(audioModule, 0); - - uint32_t volume = 0; - - if (audioModule->SpeakerVolume(&volume) != 0) { - env->Throw(jni::JavaError(env, "Get speaker volume failed")); - } - - return volume; -} - -JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_getMaxSpeakerVolume -(JNIEnv * env, jobject caller) -{ - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLEV(audioModule, 0); - - uint32_t volume = 0; - - if (audioModule->MaxSpeakerVolume(&volume) != 0) { - env->Throw(jni::JavaError(env, "Get max speaker volume failed")); - } - - return volume; -} - -JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_getMinSpeakerVolume -(JNIEnv * env, jobject caller) -{ - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLEV(audioModule, 0); - - uint32_t volume = 0; - - if (audioModule->MinSpeakerVolume(&volume) != 0) { - env->Throw(jni::JavaError(env, "Get min speaker volume failed")); - } - - return volume; -} - -JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_getMicrophoneVolume -(JNIEnv * env, jobject caller) -{ - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLEV(audioModule, 0); - - uint32_t volume = 0; - - if (audioModule->MicrophoneVolume(&volume) != 0) { - env->Throw(jni::JavaError(env, "Get microphone volume failed")); - } - - return volume; -} - -JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_getMaxMicrophoneVolume -(JNIEnv * env, jobject caller) -{ - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLEV(audioModule, 0); - - uint32_t volume = 0; - - if (audioModule->MaxMicrophoneVolume(&volume) != 0) { - env->Throw(jni::JavaError(env, "Get max microphone volume failed")); - } - - return volume; -} - -JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_getMinMicrophoneVolume -(JNIEnv * env, jobject caller) -{ - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLEV(audioModule, 0); - - uint32_t volume = 0; - - if (audioModule->MinMicrophoneVolume(&volume) != 0) { - env->Throw(jni::JavaError(env, "Get min microphone volume failed")); - } - - return volume; -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_setSpeakerVolume -(JNIEnv * env, jobject caller, jint volume) -{ - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLE(audioModule); - - if (audioModule->SetSpeakerVolume(static_cast(volume)) != 0) { - env->Throw(jni::JavaError(env, "Set speaker volume failed")); - } -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_setSpeakerMute -(JNIEnv * env, jobject caller, jboolean mute) -{ - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLE(audioModule); - - if (audioModule->SetSpeakerMute(mute) != 0) { - env->Throw(jni::JavaError(env, "Set speaker mute failed")); - } -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_setMicrophoneVolume -(JNIEnv * env, jobject caller, jint volume) -{ - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLE(audioModule); - - if (audioModule->SetMicrophoneVolume(static_cast(volume)) != 0) { - env->Throw(jni::JavaError(env, "Set microphone volume failed")); - } -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_setMicrophoneMute -(JNIEnv * env, jobject caller, jboolean mute) -{ - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLE(audioModule); - - if (audioModule->SetMicrophoneMute(mute) != 0) { - env->Throw(jni::JavaError(env, "Set microphone mute failed")); - } -} - -JNIEXPORT jlong JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_addSinkInternal -(JNIEnv * env, jobject caller, jobject jSink) -{ - if (jSink == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "AudioSink must not be null")); - return 0; - } - - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLEV(audioModule, 0); - - auto sink = new jni::AudioTransportSink(env, jni::JavaGlobalRef(env, jSink)); - - audioModule->RegisterAudioCallback(sink); - - return reinterpret_cast(sink); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_removeSinkInternal -(JNIEnv * env, jobject caller, jlong sinkHandle) -{ - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLE(audioModule); - - auto sink = reinterpret_cast(sinkHandle); - - if (sink != nullptr) { - audioModule->RegisterAudioCallback(nullptr); - - delete sink; - } -} - -JNIEXPORT jlong JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_addSourceInternal -(JNIEnv * env, jobject caller, jobject jSource) -{ - if (jSource == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "AudioSource must not be null")); - return 0; - } - - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLEV(audioModule, 0); - - auto source = new jni::AudioTransportSource(env, jni::JavaGlobalRef(env, jSource)); - - audioModule->RegisterAudioCallback(source); - - return reinterpret_cast(source); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_removeSourceInternal -(JNIEnv * env, jobject caller, jlong sourceHandle) -{ - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLE(audioModule); - - auto source = reinterpret_cast(sourceHandle); - - if (source != nullptr) { - audioModule->RegisterAudioCallback(nullptr); - - delete source; - } -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioDeviceModuleBase_disposeInternal -(JNIEnv * env, jobject caller) -{ - webrtc::AudioDeviceModule * audioModule = GetHandle(env, caller); - CHECK_HANDLE(audioModule); - - if (audioModule->Initialized()) { - audioModule->Terminate(); - } - - webrtc::RefCountReleaseStatus status = audioModule->Release(); - - if (status != webrtc::RefCountReleaseStatus::kDroppedLastRef) { - RTC_LOG(LS_WARNING) << "Native object was not deleted. A reference is still around somewhere."; - } - - SetHandle(env, caller, nullptr); - - audioModule = nullptr; -} diff --git a/webrtc-jni/src/main/cpp/src/JNI_AudioProcessing.cpp b/webrtc-jni/src/main/cpp/src/JNI_AudioProcessing.cpp deleted file mode 100644 index eb341b3..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_AudioProcessing.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_AudioProcessing.h" -#include "Exception.h" -#include "JavaArrayList.h" -#include "JavaEnums.h" -#include "JavaError.h" -#include "JavaObject.h" -#include "JavaRef.h" -#include "JavaString.h" -#include "JavaUtils.h" -#include "WebRTCContext.h" - -#include "media/audio/AudioProcessing.h" -#include "media/audio/AudioProcessingConfig.h" -#include "media/audio/AudioProcessingStreamConfig.h" -#include "api/audio/audio_frame.h" -#include "api/audio/audio_processing.h" -#include "api/audio/builtin_audio_processing_builder.h" -#include "api/scoped_refptr.h" -#include "modules/audio_processing/include/audio_processing.h" -#include "rtc_base/logging.h" - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_applyConfig -(JNIEnv * env, jobject caller, jobject config) -{ - webrtc::AudioProcessing * apm = GetHandle(env, caller); - CHECK_HANDLE(apm); - - apm->ApplyConfig(jni::AudioProcessingConfig::toNative(env, jni::JavaLocalRef(env, config))); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_setStreamDelayMs -(JNIEnv * env, jobject caller, jint delayMs) -{ - webrtc::AudioProcessing * apm = GetHandle(env, caller); - CHECK_HANDLE(apm); - - apm->set_stream_delay_ms(delayMs); -} - -JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_getStreamDelayMs -(JNIEnv * env, jobject caller) -{ - webrtc::AudioProcessing * apm = GetHandle(env, caller); - CHECK_HANDLEV(apm, 0); - - return apm->stream_delay_ms(); -} - -JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_processStream -(JNIEnv * env, jobject caller, jbyteArray src, jobject inputConfig, jobject outputConfig, jbyteArray dest) -{ - webrtc::AudioProcessing * apm = GetHandle(env, caller); - CHECK_HANDLEV(apm, 0); - - webrtc::StreamConfig srcConfig = jni::AudioProcessingStreamConfig::toNative(env, jni::JavaLocalRef(env, inputConfig)); - webrtc::StreamConfig dstConfig = jni::AudioProcessingStreamConfig::toNative(env, jni::JavaLocalRef(env, outputConfig)); - - jboolean isDstCopy = JNI_FALSE; - - jbyte * srcPtr = env->GetByteArrayElements(src, NULL); - jbyte * dstPtr = env->GetByteArrayElements(dest, &isDstCopy); - - const int16_t * srcFrame = reinterpret_cast(srcPtr); - int16_t * dstFrame = reinterpret_cast(dstPtr); - - int result; - - if (srcConfig.num_channels() == 1 && dstConfig.num_channels() == 2) { - // Up-mixing, only mono to stereo. - // For complex channel layouts a channel mixer is required. - - const size_t srcNumSamples = srcConfig.num_samples(); - const size_t dstNumChannels = dstConfig.num_channels(); - const size_t frameSize = srcNumSamples * dstNumChannels; - - if (frameSize > webrtc::AudioFrame::kMaxDataSizeSamples) { - return -9; - } - - for (int i = static_cast(srcNumSamples) - 1; i >= 0; i--) { - for (size_t j = 0; j < dstNumChannels; ++j) { - dstFrame[dstNumChannels * i + j] = srcFrame[i]; - } - } - - srcConfig.set_num_channels(dstNumChannels); - - result = apm->ProcessStream(dstFrame, srcConfig, dstConfig, dstFrame); - } - else { - // Will also down-mix if required, e.g. from stereo to mono. - result = apm->ProcessStream(srcFrame, srcConfig, dstConfig, dstFrame); - } - - if (isDstCopy == JNI_TRUE) { - jsize dstLength = env->GetArrayLength(dest); - - env->SetByteArrayRegion(dest, 0, dstLength, dstPtr); - } - - env->ReleaseByteArrayElements(src, srcPtr, JNI_ABORT); - env->ReleaseByteArrayElements(dest, dstPtr, JNI_ABORT); - - return result; -} - -JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_processReverseStream -(JNIEnv * env, jobject caller, jbyteArray src, jobject inputConfig, jobject outputConfig, jbyteArray dest) -{ - webrtc::AudioProcessing * apm = GetHandle(env, caller); - CHECK_HANDLEV(apm, 0); - - webrtc::StreamConfig srcConfig = jni::AudioProcessingStreamConfig::toNative(env, jni::JavaLocalRef(env, inputConfig)); - webrtc::StreamConfig dstConfig = jni::AudioProcessingStreamConfig::toNative(env, jni::JavaLocalRef(env, outputConfig)); - - jboolean isDstCopy = JNI_FALSE; - - jbyte * srcPtr = env->GetByteArrayElements(src, nullptr); - jbyte * dstPtr = env->GetByteArrayElements(dest, &isDstCopy); - - const int16_t * srcFrame = reinterpret_cast(srcPtr); - int16_t * dstFrame = reinterpret_cast(dstPtr); - - int result; - - if (srcConfig.num_channels() == 1 && dstConfig.num_channels() == 2) { - // Up-mixing, only mono to stereo. - // For complex channel layouts a channel mixer is required. - - const size_t srcNumSamples = srcConfig.num_samples(); - const size_t dstNumChannels = dstConfig.num_channels(); - const size_t frameSize = srcNumSamples * dstNumChannels; - - if (frameSize > webrtc::AudioFrame::kMaxDataSizeSamples) { - return -9; - } - - for (int i = static_cast(srcNumSamples) - 1; i >= 0; i--) { - for (size_t j = 0; j < dstNumChannels; ++j) { - dstFrame[dstNumChannels * i + j] = srcFrame[i]; - } - } - - srcConfig.set_num_channels(dstNumChannels); - - result = apm->ProcessReverseStream(dstFrame, srcConfig, dstConfig, dstFrame); - } - else { - // Will also down-mix if required, e.g. from stereo to mono. - result = apm->ProcessReverseStream(srcFrame, srcConfig, dstConfig, dstFrame); - } - - if (isDstCopy == JNI_TRUE) { - jsize dstLength = env->GetArrayLength(dest); - - env->SetByteArrayRegion(dest, 0, dstLength, dstPtr); - } - - env->ReleaseByteArrayElements(src, srcPtr, JNI_ABORT); - env->ReleaseByteArrayElements(dest, dstPtr, JNI_ABORT); - - return result; -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_dispose -(JNIEnv * env, jobject caller) -{ - webrtc::AudioProcessing * apm = GetHandle(env, caller); - CHECK_HANDLE(apm); - - webrtc::RefCountReleaseStatus status = apm->Release(); - - if (status != webrtc::RefCountReleaseStatus::kDroppedLastRef) { - RTC_LOG(LS_WARNING) << "Native object was not deleted. A reference is still around somewhere."; - } - - SetHandle(env, caller, nullptr); - - apm = nullptr; -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_initialize -(JNIEnv * env, jobject caller) -{ - jni::WebRTCContext * context = static_cast(javaContext); - - webrtc::scoped_refptr apm = webrtc::BuiltinAudioProcessingBuilder().Build(context->webrtcEnv); - - if (!apm) { - env->Throw(jni::JavaError(env, "Create AudioProcessing failed")); - return; - } - - SetHandle(env, caller, apm.release()); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_updateStats -(JNIEnv* env, jobject caller) -{ - webrtc::AudioProcessing * apm = GetHandle(env, caller); - CHECK_HANDLE(apm); - - jni::AudioProcessing::updateStats(apm->GetStatistics(), env, jni::JavaLocalRef(env, caller)); -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_AudioResampler.cpp b/webrtc-jni/src/main/cpp/src/JNI_AudioResampler.cpp deleted file mode 100644 index d85e8c0..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_AudioResampler.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_AudioResampler.h" -#include "Exception.h" -#include "JavaObject.h" -#include "JavaRef.h" -#include "JavaUtils.h" - -#include "common_audio/resampler/include/push_resampler.h" - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioResampler_dispose -(JNIEnv * env, jobject caller) -{ - webrtc::PushResampler * resampler = GetHandle>(env, caller); - CHECK_HANDLE(resampler); - - delete resampler; - - SetHandle(env, caller, nullptr); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioResampler_initialize -(JNIEnv * env, jobject caller) -{ - webrtc::PushResampler * resampler = new webrtc::PushResampler(); - - SetHandle(env, caller, resampler); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioResampler_initialize -(JNIEnv* env, jobject caller, jint srcSamplesPerChannel, jint dstSamplesPerChannel, jint channels) -{ - webrtc::PushResampler * resampler = new webrtc::PushResampler(srcSamplesPerChannel, dstSamplesPerChannel, channels); - - SetHandle(env, caller, resampler); -} - -JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioResampler_resampleInternal -(JNIEnv * env, jobject caller, jbyteArray samplesIn, jint srcSamplesPerChannel, jbyteArray samplesOut, jint dstSamplesPerChannel, jint channels) -{ - webrtc::PushResampler * resampler = GetHandle>(env, caller); - CHECK_HANDLEV(resampler, -1); - - jboolean isDstCopy = JNI_FALSE; - - jbyte * srcPtr = env->GetByteArrayElements(samplesIn, nullptr); - jbyte * dstPtr = env->GetByteArrayElements(samplesOut, &isDstCopy); - - int16_t * src16Ptr = reinterpret_cast(srcPtr); - int16_t * dst16Ptr = reinterpret_cast(dstPtr); - - webrtc::InterleavedView src(src16Ptr, srcSamplesPerChannel, channels); - webrtc::InterleavedView dst(dst16Ptr, dstSamplesPerChannel, channels); - - resampler->Resample(src, dst); - - if (isDstCopy == JNI_TRUE) { - jsize dstLength = env->GetArrayLength(samplesOut); - - env->SetByteArrayRegion(samplesOut, 0, dstLength, dstPtr); - } - - env->ReleaseByteArrayElements(samplesIn, srcPtr, JNI_ABORT); - env->ReleaseByteArrayElements(samplesOut, dstPtr, JNI_ABORT); - - return static_cast(dstSamplesPerChannel); -} diff --git a/webrtc-jni/src/main/cpp/src/JNI_AudioTrack.cpp b/webrtc-jni/src/main/cpp/src/JNI_AudioTrack.cpp deleted file mode 100644 index d738064..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_AudioTrack.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_AudioTrack.h" -#include "api/AudioTrackSink.h" -#include "JavaNullPointerException.h" -#include "JavaUtils.h" - -#include "api/media_stream_interface.h" - -JNIEXPORT jlong JNICALL Java_dev_onvoid_webrtc_media_audio_AudioTrack_addSinkInternal -(JNIEnv * env, jobject caller, jobject jsink) -{ - if (jsink == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "AudioTrackSink must not be null")); - return 0; - } - - webrtc::AudioTrackInterface * track = GetHandle(env, caller); - CHECK_HANDLEV(track, 0); - - auto sink = new jni::AudioTrackSink(env, jni::JavaGlobalRef(env, jsink)); - - track->AddSink(sink); - - return reinterpret_cast(sink); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_AudioTrack_removeSinkInternal -(JNIEnv * env, jobject caller, jlong sinkHandle) -{ - webrtc::AudioTrackInterface * track = GetHandle(env, caller); - CHECK_HANDLE(track); - - auto sink = reinterpret_cast(sinkHandle); - - if (sink != nullptr) { - track->RemoveSink(sink); - - delete sink; - } -} - -JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioTrack_getSignalLevel -(JNIEnv * env, jobject caller) -{ - int level = 0; - - webrtc::AudioTrackInterface * track = GetHandle(env, caller); - CHECK_HANDLEV(track, level); - - track->GetSignalLevel(&level); - - return static_cast(level); -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_CustomAudioSource.cpp b/webrtc-jni/src/main/cpp/src/JNI_CustomAudioSource.cpp deleted file mode 100644 index 84c6a47..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_CustomAudioSource.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_CustomAudioSource.h" -#include "JavaUtils.h" - -#include "media/audio/CustomAudioSource.h" - -#include "rtc_base/logging.h" - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_CustomAudioSource_initialize -(JNIEnv * env, jobject caller) -{ - std::shared_ptr sync_clock = std::make_shared(); - webrtc::scoped_refptr source = webrtc::make_ref_counted(sync_clock); - - SetHandle(env, caller, source.release()); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_CustomAudioSource_initializeWithClock -(JNIEnv * env, jobject caller, jobject javaClock) -{ - jni::SyncClock * clock = GetHandle(env, javaClock); - CHECK_HANDLE(clock); - - std::shared_ptr sync_clock(clock, [](jni::SyncClock*) {}); // Shared ownership without deleting - webrtc::scoped_refptr source = webrtc::make_ref_counted(sync_clock); - - SetHandle(env, caller, source.release()); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_CustomAudioSource_dispose -(JNIEnv * env, jobject caller) -{ - jni::CustomAudioSource * source = GetHandle(env, caller); - CHECK_HANDLE(source); - - webrtc::RefCountReleaseStatus status = source->Release(); - - if (status != webrtc::RefCountReleaseStatus::kDroppedLastRef) { - RTC_LOG(LS_WARNING) << "Native object was not deleted. A reference is still around somewhere."; - } - - SetHandle(env, caller, nullptr); - - source = nullptr; -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_CustomAudioSource_pushAudio -(JNIEnv * env, jobject caller, jbyteArray audioData, jint bits_per_sample, jint sampleRate, jint channels, jint frameCount) -{ - jni::CustomAudioSource * source = GetHandle(env, caller); - CHECK_HANDLE(source); - - jbyte * data = env->GetByteArrayElements(audioData, nullptr); - jsize length = env->GetArrayLength(audioData); - - if (data != nullptr) { - source->PushAudioData(data, bits_per_sample, sampleRate, channels, frameCount); - - env->ReleaseByteArrayElements(audioData, data, JNI_ABORT); - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_CustomVideoSource.cpp b/webrtc-jni/src/main/cpp/src/JNI_CustomVideoSource.cpp deleted file mode 100644 index 78f87c2..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_CustomVideoSource.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_CustomVideoSource.h" -#include "JavaUtils.h" -#include "api/VideoFrame.h" - -#include "media/video/CustomVideoSource.h" - -#include "rtc_base/logging.h" - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_CustomVideoSource_initialize -(JNIEnv * env, jobject caller) -{ - std::shared_ptr sync_clock = std::make_shared(); - webrtc::scoped_refptr source = webrtc::make_ref_counted(sync_clock); - - SetHandle(env, caller, source.release()); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_CustomVideoSource_initializeWithClock -(JNIEnv * env, jobject caller, jobject javaClock) -{ - jni::SyncClock * clock = GetHandle(env, javaClock); - CHECK_HANDLE(clock); - - std::shared_ptr sync_clock(clock, [](jni::SyncClock*) {}); // Shared ownership without deleting - webrtc::scoped_refptr source = webrtc::make_ref_counted(sync_clock); - - SetHandle(env, caller, source.release()); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_CustomVideoSource_dispose -(JNIEnv * env, jobject caller) -{ - jni::CustomVideoSource * source = GetHandle(env, caller); - CHECK_HANDLE(source); - - webrtc::RefCountReleaseStatus status = source->Release(); - - if (status != webrtc::RefCountReleaseStatus::kDroppedLastRef) { - RTC_LOG(LS_WARNING) << "Native object was not deleted. A reference is still around somewhere."; - } - - SetHandle(env, caller, nullptr); - - source = nullptr; -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_CustomVideoSource_pushFrame -(JNIEnv * env, jobject caller, jobject javaFrame) -{ - jni::CustomVideoSource * source = GetHandle(env, caller); - CHECK_HANDLE(source); - - if (javaFrame != nullptr) { - auto frame = jni::JavaLocalRef(env, javaFrame); - webrtc::VideoFrame nativeFrame = jni::VideoFrame::toNative(env, frame); - - source->PushFrame(nativeFrame); - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_DesktopCapturer.cpp b/webrtc-jni/src/main/cpp/src/JNI_DesktopCapturer.cpp deleted file mode 100644 index e1df6ed..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_DesktopCapturer.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_DesktopCapturer.h" -#include "JavaArrayList.h" -#include "JavaError.h" -#include "JavaUtils.h" -#include "media/video/desktop/DesktopCapturer.h" -#include "media/video/desktop/DesktopCaptureCallback.h" -#include "media/video/desktop/DesktopSource.h" - -#include "modules/desktop_capture/desktop_capturer.h" - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_desktop_DesktopCapturer_dispose -(JNIEnv * env, jobject caller) -{ - jni::DesktopCapturer * capturer = GetHandle(env, caller); - CHECK_HANDLE(capturer); - - delete capturer; - - SetHandle(env, caller, nullptr); - - auto callback = GetHandle(env, caller, "callbackHandle"); - - if (callback) { - delete callback; - } -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_video_desktop_DesktopCapturer_getDesktopSources -(JNIEnv * env, jobject caller) -{ - jni::DesktopCapturer * capturer = GetHandle(env, caller); - CHECK_HANDLEV(capturer, nullptr); - - webrtc::DesktopCapturer::SourceList sources; - - if (!capturer->GetSourceList(&sources)) { - env->Throw(jni::JavaError(env, "Get source list failed")); - return nullptr; - } - - jni::JavaArrayList sourceList(env, sources.size()); - - for (const auto & source : sources) { - sourceList.add(jni::DesktopSource::toJava(env, source)); - } - - return sourceList.listObject().release(); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_desktop_DesktopCapturer_selectSource -(JNIEnv * env, jobject caller, jobject jsource) -{ - jni::DesktopCapturer * capturer = GetHandle(env, caller); - CHECK_HANDLE(capturer); - - auto source = jni::DesktopSource::toNative(env, jni::JavaLocalRef(env, jsource)); - - if (!capturer->SelectSource(source.id)) { - env->Throw(jni::JavaError(env, "Select source failed")); - } -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_desktop_DesktopCapturer_setFocusSelectedSource -(JNIEnv * env, jobject caller, jboolean focus) -{ - jni::DesktopCapturer * capturer = GetHandle(env, caller); - CHECK_HANDLE(capturer); - - capturer->setFocusSelectedSource(focus); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_desktop_DesktopCapturer_setMaxFrameRate -(JNIEnv * env, jobject caller, jint maxFrameRate) -{ - jni::DesktopCapturer * capturer = GetHandle(env, caller); - CHECK_HANDLE(capturer); - - capturer->SetMaxFrameRate(maxFrameRate); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_desktop_DesktopCapturer_start -(JNIEnv * env, jobject caller, jobject jcallback) -{ - if (jcallback == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "DesktopCaptureCallback is null")); - return; - } - - jni::DesktopCapturer * capturer = GetHandle(env, caller); - CHECK_HANDLE(capturer); - - auto callback = new jni::DesktopCaptureCallback(env, jni::JavaGlobalRef(env, jcallback)); - - try { - SetHandle(env, caller, "callbackHandle", callback); - - capturer->Start(callback); - } - catch (...) { - ThrowCxxJavaException(env); - } -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_desktop_DesktopCapturer_captureFrame -(JNIEnv * env, jobject caller) -{ - jni::DesktopCapturer * capturer = GetHandle(env, caller); - CHECK_HANDLE(capturer); - - try { - capturer->CaptureFrame(); - } - catch (...) { - ThrowCxxJavaException(env); - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_HeadlessAudioDeviceModule.cpp b/webrtc-jni/src/main/cpp/src/JNI_HeadlessAudioDeviceModule.cpp deleted file mode 100644 index 0c4c7b7..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_HeadlessAudioDeviceModule.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_HeadlessAudioDeviceModule.h" -#include "Exception.h" -#include "JavaError.h" -#include "JavaUtils.h" -#include "WebRTCContext.h" - -#include "api/HeadlessAudioDeviceModule.h" - -#include "api/scoped_refptr.h" - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_HeadlessAudioDeviceModule_initialize -(JNIEnv* env, jobject caller) -{ - jni::WebRTCContext * context = static_cast(javaContext); - webrtc::scoped_refptr audioModule = jni::HeadlessAudioDeviceModule::Create(context->webrtcEnv); - - if (!audioModule) { - env->Throw(jni::JavaError(env, "Create HeadlessAudioDeviceModule failed")); - return; - } - - if (audioModule->Init() != 0) { - env->Throw(jni::JavaError(env, "Initialize HeadlessAudioDeviceModule failed")); - return; - } - - SetHandle(env, caller, audioModule.release()); -} diff --git a/webrtc-jni/src/main/cpp/src/JNI_MediaDevices.cpp b/webrtc-jni/src/main/cpp/src/JNI_MediaDevices.cpp deleted file mode 100644 index 125ec53..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_MediaDevices.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_MediaDevices.h" -#include "JavaArrayList.h" -#include "JavaContext.h" -#include "JavaError.h" -#include "media/DeviceChangeListener.h" -#include "media/audio/AudioDevice.h" -#include "media/audio/AudioDeviceManager.h" -#include "media/video/VideoDevice.h" -#include "media/video/VideoDeviceManager.h" -#include "media/video/VideoCaptureCapability.h" -#include "WebRTCContext.h" - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_MediaDevices_addDeviceChangeListener -(JNIEnv * env, jclass caller, jobject jListener) -{ - jni::WebRTCContext * context = static_cast(javaContext); - - try { - auto listener = new jni::DeviceChangeListener(env, jni::JavaGlobalRef(env, jListener)); - auto listenerPtr = std::shared_ptr(listener); - - context->getAudioDeviceManager()->attachHotplugListener(listenerPtr); - context->getVideoDeviceManager()->attachHotplugListener(listenerPtr); - - javaContext->addNativeRef(env, jni::JavaLocalRef(env, jListener), listenerPtr); - } - catch (...) { - ThrowCxxJavaException(env); - } -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_MediaDevices_removeDeviceChangeListener -(JNIEnv * env, jclass caller, jobject jListener) -{ - jni::WebRTCContext * context = static_cast(javaContext); - auto listener = javaContext->removeNativeRef(env, jni::JavaLocalRef(env, jListener)); - - try { - context->getAudioDeviceManager()->detachHotplugListener(listener); - context->getVideoDeviceManager()->detachHotplugListener(listener); - } - catch (...) { - ThrowCxxJavaException(env); - } -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_MediaDevices_getDefaultAudioRenderDevice -(JNIEnv * env, jclass caller) -{ - jni::WebRTCContext * context = static_cast(javaContext); - - try { - auto device = context->getAudioDeviceManager()->getDefaultAudioPlaybackDevice(); - - return jni::AudioDevice::toJavaAudioDevice(env, device).release(); - } - catch (...) { - ThrowCxxJavaException(env); - } - - return nullptr; -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_MediaDevices_getDefaultAudioCaptureDevice -(JNIEnv * env, jclass caller) -{ - jni::WebRTCContext * context = static_cast(javaContext); - - try { - auto device = context->getAudioDeviceManager()->getDefaultAudioCaptureDevice(); - - return jni::AudioDevice::toJavaAudioDevice(env, device).release(); - } - catch (...) { - ThrowCxxJavaException(env); - } - - return nullptr; -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_MediaDevices_getAudioRenderDevices -(JNIEnv * env, jclass caller) -{ - try { - jni::WebRTCContext * context = static_cast(javaContext); - - auto devices = context->getAudioDeviceManager()->getAudioPlaybackDevices(); - - jni::JavaArrayList deviceList(env, devices.size()); - - for (const auto & device : devices) { - deviceList.add(jni::AudioDevice::toJavaAudioDevice(env, device)); - } - - return deviceList.listObject().release(); - } - catch (...) { - ThrowCxxJavaException(env); - } - - return nullptr; -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_MediaDevices_getAudioCaptureDevices -(JNIEnv * env, jclass caller) -{ - try { - jni::WebRTCContext * context = static_cast(javaContext); - - auto devices = context->getAudioDeviceManager()->getAudioCaptureDevices(); - - jni::JavaArrayList deviceList(env, devices.size()); - - for (const auto & device : devices) { - deviceList.add(jni::AudioDevice::toJavaAudioDevice(env, device)); - } - - return deviceList.listObject().release(); - } - catch (...) { - ThrowCxxJavaException(env); - } - - return nullptr; -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_MediaDevices_getVideoCaptureDevices -(JNIEnv * env, jclass caller) -{ - try { - jni::WebRTCContext * context = static_cast(javaContext); - - auto devices = context->getVideoDeviceManager()->getVideoCaptureDevices(); - - jni::JavaArrayList deviceList(env, devices.size()); - - for (const auto & device : devices) { - deviceList.add(jni::VideoDevice::toJavaVideoDevice(env, *device.get())); - } - - return deviceList.listObject().release(); - } - catch (...) { - ThrowCxxJavaException(env); - } - - return nullptr; -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_MediaDevices_getVideoCaptureCapabilities -(JNIEnv * env, jclass caller, jobject device) -{ - if (!device) { - env->Throw(jni::JavaNullPointerException(env, "VideoDevice is null")); - return nullptr; - } - - try { - jni::WebRTCContext * context = static_cast(javaContext); - - auto dev = jni::VideoDevice::toNativeVideoDevice(env, jni::JavaLocalRef(env, device)); - auto capabilities = context->getVideoDeviceManager()->getVideoCaptureCapabilities(dev); - - jni::JavaArrayList capabilityList(env, capabilities.size()); - - for (const auto & capability : capabilities) { - capabilityList.add(jni::VideoCaptureCapability::toJava(env, capability)); - } - - return capabilityList.listObject().release(); - } - catch (...) { - ThrowCxxJavaException(env); - } - - return nullptr; -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_MediaSource.cpp b/webrtc-jni/src/main/cpp/src/JNI_MediaSource.cpp deleted file mode 100644 index 4a57629..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_MediaSource.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_MediaSource.h" -#include "JavaEnums.h" -#include "JavaUtils.h" - -#include "api/media_stream_interface.h" - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_MediaSource_getState -(JNIEnv * env, jobject caller) -{ - webrtc::MediaSourceInterface * source = GetHandle(env, caller); - CHECK_HANDLEV(source, nullptr); - - return jni::JavaEnums::toJava(env, source->state()).release(); -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_MediaStream.cpp b/webrtc-jni/src/main/cpp/src/JNI_MediaStream.cpp deleted file mode 100644 index 5206845..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_MediaStream.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_MediaStream.h" -#include "api/WebRTCUtils.h" -#include "JavaError.h" -#include "JavaFactories.h" -#include "JavaString.h" -#include "JavaUtils.h" - -#include "api/media_stream_interface.h" -#include "rtc_base/logging.h" - -JNIEXPORT jstring JNICALL Java_dev_onvoid_webrtc_media_MediaStream_id -(JNIEnv * env, jobject caller) -{ - webrtc::MediaStreamInterface * stream = GetHandle(env, caller); - CHECK_HANDLEV(stream, nullptr); - - return jni::JavaString::toJava(env, stream->id()); -} - -JNIEXPORT jobjectArray JNICALL Java_dev_onvoid_webrtc_media_MediaStream_getAudioTracks -(JNIEnv * env, jobject caller) -{ - webrtc::MediaStreamInterface * stream = GetHandle(env, caller); - CHECK_HANDLEV(stream, nullptr); - - jni::JavaLocalRef objectArray; - - try { - objectArray = jni::createObjectArray(env, stream->GetAudioTracks()); - } - catch (...) { - ThrowCxxJavaException(env); - } - - return objectArray; -} - -JNIEXPORT jobjectArray JNICALL Java_dev_onvoid_webrtc_media_MediaStream_getVideoTracks -(JNIEnv * env, jobject caller) -{ - webrtc::MediaStreamInterface * stream = GetHandle(env, caller); - CHECK_HANDLEV(stream, nullptr); - - jni::JavaLocalRef objectArray; - - try { - objectArray = jni::createObjectArray(env, stream->GetVideoTracks()); - } - catch (...) { - ThrowCxxJavaException(env); - } - - return objectArray; -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_MediaStream_addTrack -(JNIEnv * env, jobject caller, jobject jTrack) -{ - webrtc::MediaStreamInterface * stream = GetHandle(env, caller); - CHECK_HANDLE(stream); - - webrtc::MediaStreamTrackInterface * track = GetHandle(env, jTrack); - CHECK_HANDLE(track); - - if (webrtc::AudioTrackInterface * t = dynamic_cast(track)) { - stream->AddTrack(webrtc::scoped_refptr(t)); - } - else if (webrtc::VideoTrackInterface * t = dynamic_cast(track)) { - stream->AddTrack(webrtc::scoped_refptr(t)); - } -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_MediaStream_removeTrack -(JNIEnv * env, jobject caller, jobject jTrack) -{ - webrtc::MediaStreamInterface * stream = GetHandle(env, caller); - CHECK_HANDLE(stream); - - webrtc::MediaStreamTrackInterface * track = GetHandle(env, jTrack); - CHECK_HANDLE(track); - - if (webrtc::AudioTrackInterface * t = dynamic_cast(track)) { - stream->RemoveTrack(webrtc::scoped_refptr(t)); - } - else if (webrtc::VideoTrackInterface * t = dynamic_cast(track)) { - stream->RemoveTrack(webrtc::scoped_refptr(t)); - } -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_MediaStream_dispose -(JNIEnv * env, jobject caller) -{ - webrtc::MediaStreamInterface * stream = GetHandle(env, caller); - CHECK_HANDLE(stream); - - webrtc::RefCountReleaseStatus status = stream->Release(); - - if (status != webrtc::RefCountReleaseStatus::kDroppedLastRef) { - RTC_LOG(LS_WARNING) << "Native object was not deleted. A reference is still around somewhere."; - } - - SetHandle(env, caller, nullptr); - - stream = nullptr; -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_MediaStreamTrack.cpp b/webrtc-jni/src/main/cpp/src/JNI_MediaStreamTrack.cpp deleted file mode 100644 index 011e6ac..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_MediaStreamTrack.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_MediaStreamTrack.h" -#include "JavaContext.h" -#include "JavaEnums.h" -#include "JavaError.h" -#include "JavaFactories.h" -#include "JavaString.h" -#include "WebRTCContext.h" - -#include "media/MediaStreamTrackObserver.h" - -#include "api/media_stream_interface.h" -#include "rtc_base/logging.h" - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_MediaStreamTrack_dispose -(JNIEnv * env, jobject caller) -{ - webrtc::MediaStreamTrackInterface * track = GetHandle(env, caller); - CHECK_HANDLE(track); - - webrtc::RefCountReleaseStatus status = track->Release(); - - if (status != webrtc::RefCountReleaseStatus::kDroppedLastRef) { - env->Throw(jni::JavaError(env, "Native object was not deleted. A reference is still around somewhere.")); - } - else { - SetHandle(env, caller, nullptr); - track = nullptr; - } -} - -JNIEXPORT jstring JNICALL Java_dev_onvoid_webrtc_media_MediaStreamTrack_getKind -(JNIEnv * env, jobject caller) -{ - webrtc::MediaStreamTrackInterface * track = GetHandle(env, caller); - CHECK_HANDLEV(track, nullptr); - - return jni::JavaString::toJava(env, track->kind()).release(); -} - -JNIEXPORT jstring JNICALL Java_dev_onvoid_webrtc_media_MediaStreamTrack_getId -(JNIEnv * env, jobject caller) -{ - webrtc::MediaStreamTrackInterface * track = GetHandle(env, caller); - CHECK_HANDLEV(track, nullptr); - - return jni::JavaString::toJava(env, track->id()).release(); -} - -JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_media_MediaStreamTrack_isEnabled -(JNIEnv * env, jobject caller) -{ - webrtc::MediaStreamTrackInterface * track = GetHandle(env, caller); - CHECK_HANDLEV(track, false); - - return static_cast(track->enabled()); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_MediaStreamTrack_setEnabled -(JNIEnv * env, jobject caller, jboolean enabled) -{ - webrtc::MediaStreamTrackInterface * track = GetHandle(env, caller); - CHECK_HANDLE(track); - - track->set_enabled(static_cast(enabled)); -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_MediaStreamTrack_getState -(JNIEnv * env, jobject caller) -{ - webrtc::MediaStreamTrackInterface * track = GetHandle(env, caller); - CHECK_HANDLEV(track, nullptr); - - return jni::JavaEnums::toJava(env, track->state()).release(); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_MediaStreamTrack_addEndedEventListener -(JNIEnv * env, jobject caller, jobject jListener) -{ - webrtc::MediaStreamTrackInterface * track = GetHandle(env, caller); - CHECK_HANDLE(track); - - try { - jni::MediaStreamTrackObserver * observer = new jni::MediaStreamTrackObserver(env, jni::JavaGlobalRef(env, jListener), track, jni::MediaStreamTrackEvent::ended); - auto observerPtr = std::shared_ptr(observer); - - track->RegisterObserver(observer); - - javaContext->addNativeRef(env, jni::JavaLocalRef(env, jListener), observerPtr); - } - catch (...) { - ThrowCxxJavaException(env); - } -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_MediaStreamTrack_removeEndedEventListener -(JNIEnv * env, jobject caller, jobject jListener) -{ - webrtc::MediaStreamTrackInterface * track = GetHandle(env, caller); - CHECK_HANDLE(track); - - try { - auto observerPtr = javaContext->removeNativeRef(env, jni::JavaLocalRef(env, jListener)); - - if (observerPtr) { - track->UnregisterObserver(observerPtr.get()); - } - } - catch (...) { - ThrowCxxJavaException(env); - } -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_MediaStreamTrack_addMuteEventListener -(JNIEnv * env, jobject caller, jobject jListener) -{ - webrtc::MediaStreamTrackInterface * track = GetHandle(env, caller); - CHECK_HANDLE(track); - - try { - jni::MediaStreamTrackObserver * observer = new jni::MediaStreamTrackObserver(env, jni::JavaGlobalRef(env, jListener), track, jni::MediaStreamTrackEvent::mute); - auto observerPtr = std::shared_ptr(observer); - - track->RegisterObserver(observer); - - javaContext->addNativeRef(env, jni::JavaLocalRef(env, jListener), observerPtr); - } - catch (...) { - ThrowCxxJavaException(env); - } -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_MediaStreamTrack_removeMuteEventListener -(JNIEnv * env, jobject caller, jobject jListener) -{ - webrtc::MediaStreamTrackInterface * track = GetHandle(env, caller); - CHECK_HANDLE(track); - - try { - auto observerPtr = javaContext->removeNativeRef(env, jni::JavaLocalRef(env, jListener)); - - if (observerPtr) { - track->UnregisterObserver(observerPtr.get()); - } - } - catch (...) { - ThrowCxxJavaException(env); - } -} diff --git a/webrtc-jni/src/main/cpp/src/JNI_NativeI420Buffer.cpp b/webrtc-jni/src/main/cpp/src/JNI_NativeI420Buffer.cpp deleted file mode 100644 index 10fb32f..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_NativeI420Buffer.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_NativeI420Buffer.h" -#include "api/VideoFrame.h" -#include "JavaRuntimeException.h" - -#include "api/video/i420_buffer.h" -#include "libyuv/scale.h" - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_video_NativeI420Buffer_allocate -(JNIEnv * env, jclass caller, jint width, jint height) -{ - webrtc::scoped_refptr i420Buffer = webrtc::I420Buffer::Create(width, height); - - jni::JavaLocalRef jBuffer = jni::I420Buffer::toJava(env, i420Buffer); - - i420Buffer->AddRef(); - - return jBuffer.release(); -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_media_video_NativeI420Buffer_copy -(JNIEnv* env, jclass caller, jint width, jint height, jobject jSrcY, jint srcStrideY, - jobject jSrcU, jint srcStrideU, jobject jSrcV, jint srcStrideV) -{ - const uint8_t * src_y = static_cast(env->GetDirectBufferAddress(jSrcY)); - const uint8_t * src_u = static_cast(env->GetDirectBufferAddress(jSrcU)); - const uint8_t * src_v = static_cast(env->GetDirectBufferAddress(jSrcV)); - - webrtc::scoped_refptr i420Buffer = webrtc::I420Buffer::Copy(width, height, - src_y, srcStrideY, src_u, srcStrideU, src_v, srcStrideV); - - jni::JavaLocalRef jBuffer = jni::I420Buffer::toJava(env, i420Buffer); - - i420Buffer->AddRef(); - - return jBuffer.release(); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_NativeI420Buffer_cropAndScale -(JNIEnv * env, jclass caller, jobject jSrcY, jint srcStrideY, jobject jSrcU, jint srcStrideU, - jobject jSrcV, jint srcStrideV, jint cropX, jint cropY, jint cropW, jint cropH, - jobject jDstY, jint dstStrideY, jobject jDstU, jint dstStrideU, jobject jDstV, jint dstStrideV, - jint scaleW, jint scaleH) -{ - const uint8_t * src_y = static_cast(env->GetDirectBufferAddress(jSrcY)); - const uint8_t * src_u = static_cast(env->GetDirectBufferAddress(jSrcU)); - const uint8_t * src_v = static_cast(env->GetDirectBufferAddress(jSrcV)); - uint8_t * dst_y = static_cast(env->GetDirectBufferAddress(jDstY)); - uint8_t * dst_u = static_cast(env->GetDirectBufferAddress(jDstU)); - uint8_t * dst_v = static_cast(env->GetDirectBufferAddress(jDstV)); - - // Perform cropping using pointer arithmetic. - src_y += cropX + cropY * srcStrideY; - src_u += cropX / 2 + cropY / 2 * srcStrideU; - src_v += cropX / 2 + cropY / 2 * srcStrideV; - - bool ret = libyuv::I420Scale( - src_y, srcStrideY, src_u, srcStrideU, src_v, srcStrideV, cropW, - cropH, dst_y, dstStrideY, dst_u, dstStrideU, dst_v, - dstStrideV, scaleW, scaleH, libyuv::kFilterBox); - - if (ret != 0) { - env->Throw(jni::JavaRuntimeException(env, "I420Buffer crop and scale failed")); - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp b/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp index 63f15b0..33a1761 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp @@ -30,99 +30,56 @@ #include "JavaUtils.h" #include "api/create_peerconnection_factory.h" -#include "api/audio_codecs/builtin_audio_decoder_factory.h" -#include "api/audio_codecs/builtin_audio_encoder_factory.h" - -#ifdef __APPLE__ -#include "sdk/objc/components/video_codec/RTCDefaultVideoDecoderFactory.h" -#include "sdk/objc/components/video_codec/RTCDefaultVideoEncoderFactory.h" -#include "sdk/objc/native/api/video_decoder_factory.h" -#include "sdk/objc/native/api/video_encoder_factory.h" -#else -#include "api/video_codecs/builtin_video_decoder_factory.h" -#include "api/video_codecs/builtin_video_encoder_factory.h" -#include "api/video_codecs/video_decoder_factory_template_dav1d_adapter.h" -#include "api/video_codecs/video_decoder_factory_template_libvpx_vp8_adapter.h" -#include "api/video_codecs/video_decoder_factory_template_libvpx_vp9_adapter.h" -#include "api/video_codecs/video_decoder_factory_template_open_h264_adapter.h" -#include "api/video_codecs/video_encoder_factory_template_libaom_av1_adapter.h" -#include "api/video_codecs/video_encoder_factory_template_libvpx_vp8_adapter.h" -#include "api/video_codecs/video_encoder_factory_template_libvpx_vp9_adapter.h" -#include "api/video_codecs/video_encoder_factory_template_open_h264_adapter.h" -#endif - -#include "api/video_codecs/video_decoder_factory.h" -#include "api/video_codecs/video_decoder_factory_template.h" -#include "api/video_codecs/video_encoder_factory.h" -#include "api/video_codecs/video_encoder_factory_template.h" JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_initialize -(JNIEnv * env, jobject caller, jobject audioModule, jobject audioProcessing) +(JNIEnv * env, jobject caller) { webrtc::AudioDeviceModule * audioDevModule = (audioModule != nullptr) ? GetHandle(env, audioModule) : nullptr; try { - auto networkThread = webrtc::Thread::CreateWithSocketServer(); - networkThread->SetName("webrtc_jni_network_thread", nullptr); - - auto signalingThread = webrtc::Thread::Create(); - signalingThread->SetName("webrtc_jni_signaling_thread", nullptr); - - auto workerThread = webrtc::Thread::Create(); - workerThread->SetName("webrtc_jni_worker_thread", nullptr); - - if (!networkThread->Start()) { - throw jni::Exception("Start network thread failed"); - } - if (!signalingThread->Start()) { - throw jni::Exception("Start signaling thread failed"); - } - if (!workerThread->Start()) { - throw jni::Exception("Start worker thread failed"); - } - - webrtc::AudioProcessing * processing = (audioProcessing != nullptr) - ? GetHandle(env, audioProcessing) - : nullptr; - webrtc::scoped_refptr apm(processing); - webrtc::scoped_refptr adm(audioDevModule); - - auto factory = webrtc::CreatePeerConnectionFactory( - networkThread.get(), - workerThread.get(), - signalingThread.get(), - adm, - webrtc::CreateBuiltinAudioEncoderFactory(), - webrtc::CreateBuiltinAudioDecoderFactory(), -#ifdef __APPLE__ - webrtc::ObjCToNativeVideoEncoderFactory([[RTC_OBJC_TYPE(RTCDefaultVideoEncoderFactory) alloc] init]), - webrtc::ObjCToNativeVideoDecoderFactory([[RTC_OBJC_TYPE(RTCDefaultVideoDecoderFactory) alloc] init]), -#else - std::make_unique>(), - std::make_unique>(), -#endif - nullptr, - apm); - - if (factory != nullptr) { - SetHandle(env, caller, factory.release()); - SetHandle(env, caller, "networkThreadHandle", networkThread.release()); - SetHandle(env, caller, "signalingThreadHandle", signalingThread.release()); - SetHandle(env, caller, "workerThreadHandle", workerThread.release()); - } - else { - throw jni::Exception("Create PeerConnectionFactory failed"); - } + auto networkThread = webrtc::Thread::CreateWithSocketServer(); + networkThread->SetName("webrtc_jni_network_thread", nullptr); + + auto signalingThread = webrtc::Thread::Create(); + signalingThread->SetName("webrtc_jni_signaling_thread", nullptr); + + auto workerThread = webrtc::Thread::Create(); + workerThread->SetName("webrtc_jni_worker_thread", nullptr); + + if (!networkThread->Start()) { + throw jni::Exception("Start network thread failed"); + } + if (!signalingThread->Start()) { + throw jni::Exception("Start signaling thread failed"); + } + if (!workerThread->Start()) { + throw jni::Exception("Start worker thread failed"); + } + + auto factory = webrtc::CreatePeerConnectionFactory( + networkThread.get(), + workerThread.get(), + signalingThread.get(), + nullptr, // AudioDeviceModule + nullptr, // AudioEncoderFactory + nullptr, // AudioDecoderFactory + nullptr, // VideoEncoderFactory + nullptr, // VideoDecoderFactory + nullptr, // AudioMixer + nullptr // AudioProcessing + ); + + if (factory != nullptr) { + SetHandle(env, caller, factory.release()); + SetHandle(env, caller, "networkThreadHandle", networkThread.release()); + SetHandle(env, caller, "signalingThreadHandle", signalingThread.release()); + SetHandle(env, caller, "workerThreadHandle", workerThread.release()); + } + else { + throw jni::Exception("Create PeerConnectionFactory failed"); + } } catch (...) { ThrowCxxJavaException(env); @@ -168,80 +125,6 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_dispose } } -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_createAudioSource -(JNIEnv * env, jobject caller, jobject jAudioOptions) -{ - if (jAudioOptions == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "AudioOptions is null")); - return nullptr; - } - - webrtc::PeerConnectionFactoryInterface * factory = GetHandle(env, caller); - CHECK_HANDLEV(factory, nullptr); - - auto audioOptions = jni::AudioOptions::toNative(env, jni::JavaLocalRef(env, jAudioOptions)); - - webrtc::scoped_refptr audioSource = factory->CreateAudioSource(audioOptions); - - if (audioSource == nullptr) { - env->Throw(jni::JavaError(env, "Create audio-track source failed")); - return nullptr; - } - - return jni::JavaFactories::create(env, audioSource.release()).release(); -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_createAudioTrack -(JNIEnv * env, jobject caller, jstring jlabel, jobject jsource) -{ - if (jlabel == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "Audio track label is null")); - return nullptr; - } - if (jsource == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "AudioTrackSource is null")); - return nullptr; - } - - webrtc::PeerConnectionFactoryInterface * factory = GetHandle(env, caller); - CHECK_HANDLEV(factory, nullptr); - - webrtc::AudioSourceInterface * source = GetHandle(env, jsource); - CHECK_HANDLEV(source, nullptr); - - std::string label = jni::JavaString::toNative(env, jni::JavaLocalRef(env, jlabel)); - - webrtc::scoped_refptr audioTrack = factory->CreateAudioTrack(label, source); - - return jni::JavaFactories::create(env, audioTrack.release()).release(); -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_createVideoTrack -(JNIEnv * env, jobject caller, jstring jlabel, jobject jsource) -{ - if (jlabel == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "Video track label is null")); - return nullptr; - } - if (jsource == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "VideoTrackSource is null")); - return nullptr; - } - - webrtc::PeerConnectionFactoryInterface * factory = GetHandle(env, caller); - CHECK_HANDLEV(factory, nullptr); - - webrtc::VideoTrackSourceInterface * source = GetHandle(env, jsource); - CHECK_HANDLEV(source, nullptr); - - std::string label = jni::JavaString::toNative(env, jni::JavaLocalRef(env, jlabel)); - - webrtc::scoped_refptr videoTrack = factory->CreateVideoTrack( - webrtc::scoped_refptr(source), label); - - return jni::JavaFactories::create(env, videoTrack.release()).release(); -} - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_createPeerConnection (JNIEnv * env, jobject caller, jobject jConfig, jobject jobserver) { @@ -281,28 +164,4 @@ JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_createPee } return nullptr; -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_getRtpReceiverCapabilities -(JNIEnv * env, jobject caller, jobject mediaType) -{ - webrtc::PeerConnectionFactoryInterface * factory = GetHandle(env, caller); - CHECK_HANDLEV(factory, nullptr); - - auto type = jni::JavaEnums::toNative(env, mediaType); - auto capabilities = factory->GetRtpReceiverCapabilities(type); - - return jni::RTCRtpCapabilities::toJava(env, capabilities).release(); -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_getRtpSenderCapabilities -(JNIEnv * env, jobject caller, jobject mediaType) -{ - webrtc::PeerConnectionFactoryInterface * factory = GetHandle(env, caller); - CHECK_HANDLEV(factory, nullptr); - - auto type = jni::JavaEnums::toNative(env, mediaType); - auto capabilities = factory->GetRtpSenderCapabilities(type); - - return jni::RTCRtpCapabilities::toJava(env, capabilities).release(); } \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_PowerManagement.cpp b/webrtc-jni/src/main/cpp/src/JNI_PowerManagement.cpp deleted file mode 100644 index 71ebc9d..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_PowerManagement.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_PowerManagement.h" -#include "WebRTCContext.h" - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_desktop_PowerManagement_enableUserActivity -(JNIEnv * env, jobject caller) -{ - jni::WebRTCContext * context = static_cast(javaContext); - - try { - context->getPowerManagement()->enableUserActivity(); - } - catch (...) { - ThrowCxxJavaException(env); - } - - fflush(NULL); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_desktop_PowerManagement_disableUserActivity -(JNIEnv * env, jobject caller) -{ - jni::WebRTCContext * context = static_cast(javaContext); - - try { - context->getPowerManagement()->disableUserActivity(); - } - catch (...) { - ThrowCxxJavaException(env); - } - - fflush(NULL); -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_RTCDtmfSender.cpp b/webrtc-jni/src/main/cpp/src/JNI_RTCDtmfSender.cpp deleted file mode 100644 index e6dd5c7..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_RTCDtmfSender.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_RTCDtmfSender.h" -#include "api/RTCDtmfSenderObserver.h" -#include "JavaString.h" -#include "JavaUtils.h" - -#include "api/dtmf_sender_interface.h" - -JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_RTCDtmfSender_canInsertDtmf -(JNIEnv * env, jobject caller) -{ - webrtc::DtmfSenderInterface * sender = GetHandle(env, caller); - CHECK_HANDLEV(sender, false); - - return static_cast(sender->CanInsertDtmf()); -} - -JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_RTCDtmfSender_insertDtmf -(JNIEnv * env, jobject caller, jstring jTones, jint duration, jint interToneGap) -{ - webrtc::DtmfSenderInterface * sender = GetHandle(env, caller); - CHECK_HANDLEV(sender, false); - - std::string tones = jni::JavaString::toNative(env, jni::JavaLocalRef(env, jTones)); - - return static_cast(sender->InsertDtmf(tones, static_cast(duration), static_cast(interToneGap))); -} - -JNIEXPORT jstring JNICALL Java_dev_onvoid_webrtc_RTCDtmfSender_tones -(JNIEnv * env, jobject caller) -{ - webrtc::DtmfSenderInterface * sender = GetHandle(env, caller); - CHECK_HANDLEV(sender, nullptr); - - return jni::JavaString::toJava(env, sender->tones()).release(); -} - -JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_RTCDtmfSender_duration -(JNIEnv * env, jobject caller) -{ - webrtc::DtmfSenderInterface * sender = GetHandle(env, caller); - CHECK_HANDLEV(sender, 0); - - return static_cast(sender->duration()); -} - -JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_RTCDtmfSender_interToneGap -(JNIEnv * env, jobject caller) -{ - webrtc::DtmfSenderInterface * sender = GetHandle(env, caller); - CHECK_HANDLEV(sender, 0); - - return static_cast(sender->inter_tone_gap()); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDtmfSender_registerObserver -(JNIEnv * env, jobject caller, jobject jObserver) -{ - webrtc::DtmfSenderInterface * sender = GetHandle(env, caller); - CHECK_HANDLE(sender); - - sender->RegisterObserver(new jni::RTCDtmfSenderObserver(env, jni::JavaGlobalRef(env, jObserver))); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDtmfSender_unregisterObserver -(JNIEnv * env, jobject caller) -{ - webrtc::DtmfSenderInterface * sender = GetHandle(env, caller); - CHECK_HANDLE(sender); - - sender->UnregisterObserver(); -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_RTCPeerConnection.cpp b/webrtc-jni/src/main/cpp/src/JNI_RTCPeerConnection.cpp index a473517..3c6df3a 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_RTCPeerConnection.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_RTCPeerConnection.cpp @@ -22,7 +22,6 @@ #include "api/RTCDataChannelInit.h" #include "api/RTCIceCandidate.h" #include "api/RTCOfferOptions.h" -#include "api/RTCRtpTransceiverInit.h" #include "api/RTCSessionDescription.h" #include "api/RTCStatsCollectorCallback.h" #include "api/WebRTCUtils.h" @@ -39,8 +38,6 @@ #include "JavaUtils.h" #include "api/peer_connection_interface.h" -#include "api/rtp_receiver_interface.h" -#include "api/rtp_sender_interface.h" #include #include @@ -99,97 +96,6 @@ JNIEXPORT jobjectArray JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getTrans return objectArray.release(); } -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_addTrack -(JNIEnv * env, jobject caller, jobject jTrack, jobject jStreamIds) -{ - if (jTrack == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "MediaStreamTrack must not be null")); - return nullptr; - } - if (jStreamIds == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "Stream IDs must not be null")); - return nullptr; - } - - webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); - CHECK_HANDLEV(pc, nullptr); - - webrtc::MediaStreamTrackInterface * track = GetHandle(env, jTrack); - CHECK_HANDLEV(track, nullptr); - - std::vector streamIDs = jni::JavaList::toStringVector(env, jni::JavaLocalRef(env, jStreamIds)); - - auto result = pc->AddTrack(webrtc::scoped_refptr(track), streamIDs); - - if (result.ok()) { - auto sender = result.MoveValue(); - - return jni::JavaFactories::create(env, sender.release()).release(); - } - - env->Throw(jni::JavaRuntimeException(env, jni::RTCErrorToString(result.error()).c_str())); - - return nullptr; -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_removeTrack -(JNIEnv * env, jobject caller, jobject jSender) -{ - if (jSender == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "RTCRtpSender must not be null")); - return; - } - - webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); - CHECK_HANDLE(pc); - - webrtc::RtpSenderInterface * sender = GetHandle(env, jSender); - CHECK_HANDLE(sender); - - auto result = pc->RemoveTrackOrError(webrtc::scoped_refptr(sender)); - - if (!result.ok()) { - env->Throw(jni::JavaRuntimeException(env, "Remove track (RTCRtpSender) failed: %s %s", - ToString(result.type()), result.message())); - } -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_addTransceiver -(JNIEnv * env, jobject caller, jobject jTrack, jobject jTransceiverInit) -{ - if (jTrack == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "MediaStreamTrack must not be null")); - return nullptr; - } - - webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); - CHECK_HANDLEV(pc, nullptr); - - webrtc::MediaStreamTrackInterface * track = GetHandle(env, jTrack); - CHECK_HANDLEV(track, nullptr); - - webrtc::RTCErrorOr> result; - - if (jTransceiverInit != nullptr) { - auto init = jni::RTCRtpTransceiverInit::toNative(env, jni::JavaLocalRef(env, jTransceiverInit)); - - result = pc->AddTransceiver(webrtc::scoped_refptr(track), init); - } - else { - result = pc->AddTransceiver(webrtc::scoped_refptr(track)); - } - - if (result.ok()) { - auto transceiver = result.MoveValue(); - - return jni::JavaFactories::create(env, transceiver.release()).release(); - } - - env->Throw(jni::JavaRuntimeException(env, jni::RTCErrorToString(result.error()).c_str())); - - return nullptr; -} - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_createDataChannel (JNIEnv * env, jobject caller, jstring jLabel, jobject jDict) { @@ -536,52 +442,6 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getStats__Ldev_o pc->GetStats(callback); } -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getStats__Ldev_onvoid_webrtc_RTCRtpReceiver_2Ldev_onvoid_webrtc_RTCStatsCollectorCallback_2 -(JNIEnv * env, jobject caller, jobject jreceiver, jobject jcallback) -{ - webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); - CHECK_HANDLE(pc); - - if (jreceiver == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "RTCRtpReceiver is null")); - return; - } - if (jcallback == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "RTCStatsCollectorCallback is null")); - return; - } - - webrtc::RtpReceiverInterface * receiver = GetHandle(env, jreceiver); - CHECK_HANDLE(receiver); - - auto callback = new webrtc::RefCountedObject(env, jni::JavaGlobalRef(env, jcallback)); - - pc->GetStats(webrtc::scoped_refptr(receiver), webrtc::scoped_refptr(callback)); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getStats__Ldev_onvoid_webrtc_RTCRtpSender_2Ldev_onvoid_webrtc_RTCStatsCollectorCallback_2 -(JNIEnv * env, jobject caller, jobject jsender, jobject jcallback) -{ - webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); - CHECK_HANDLE(pc); - - if (jsender == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "RTCRtpSender is null")); - return; - } - if (jcallback == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "RTCStatsCollectorCallback is null")); - return; - } - - webrtc::RtpSenderInterface * sender = GetHandle(env, jsender); - CHECK_HANDLE(sender); - - auto callback = new webrtc::RefCountedObject(env, jni::JavaGlobalRef(env, jcallback)); - - pc->GetStats(webrtc::scoped_refptr(sender), webrtc::scoped_refptr(callback)); -} - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_restartIce (JNIEnv * env, jobject caller) { diff --git a/webrtc-jni/src/main/cpp/src/JNI_RTCRtpReceiver.cpp b/webrtc-jni/src/main/cpp/src/JNI_RTCRtpReceiver.cpp deleted file mode 100644 index 7e74734..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_RTCRtpReceiver.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_RTCRtpReceiver.h" -#include "api/RTCRtpParameters.h" -#include "api/RTCRtpContributingSource.h" -#include "api/RTCRtpSynchronizationSource.h" -#include "JavaFactories.h" -#include "JavaList.h" -#include "JavaUtils.h" - -#include "api/rtp_receiver_interface.h" - -#include - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpReceiver_getTrack -(JNIEnv * env, jobject caller) -{ - webrtc::RtpReceiverInterface * receiver = GetHandle(env, caller); - CHECK_HANDLEV(receiver, nullptr); - - webrtc::scoped_refptr track = receiver->track(); - - if (webrtc::AudioTrackInterface * t = dynamic_cast(track.get())) { - return jni::JavaFactories::create(env, t).release(); - } - else if (webrtc::VideoTrackInterface * t = dynamic_cast(track.get())) { - return jni::JavaFactories::create(env, t).release(); - } - - return nullptr; -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpReceiver_getTransport -(JNIEnv * env, jobject caller) -{ - webrtc::RtpReceiverInterface * receiver = GetHandle(env, caller); - CHECK_HANDLEV(receiver, nullptr); - - auto transport = receiver->dtls_transport(); - - return jni::JavaFactories::create(env, transport.get()).release(); -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpReceiver_getParameters -(JNIEnv * env, jobject caller) -{ - webrtc::RtpReceiverInterface * receiver = GetHandle(env, caller); - CHECK_HANDLEV(receiver, nullptr); - - return jni::RTCRtpParameters::toJava(env, receiver->GetParameters()).release(); -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpReceiver_getContributingSources -(JNIEnv * env, jobject caller) -{ - webrtc::RtpReceiverInterface * receiver = GetHandle(env, caller); - CHECK_HANDLEV(receiver, nullptr); - - std::vector sources = receiver->GetSources(); - std::vector csrc; - - std::copy_if(sources.begin(), sources.end(), std::back_inserter(csrc), - [](webrtc::RtpSource s) { return s.source_type() == webrtc::RtpSourceType::CSRC; }); - - auto list = jni::JavaList::toArrayList(env, csrc, jni::RTCRtpContributingSource::toJava); - - return list.release(); -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpReceiver_getSynchronizationSources -(JNIEnv * env, jobject caller) -{ - webrtc::RtpReceiverInterface * receiver = GetHandle(env, caller); - CHECK_HANDLEV(receiver, nullptr); - - std::vector sources = receiver->GetSources(); - std::vector ssrc; - - std::copy_if(sources.begin(), sources.end(), std::back_inserter(ssrc), - [](webrtc::RtpSource s) { return s.source_type() == webrtc::RtpSourceType::SSRC; }); - - auto list = jni::JavaList::toArrayList(env, ssrc, jni::RTCRtpSynchronizationSource::toJava); - - return list.release(); -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_RTCRtpSender.cpp b/webrtc-jni/src/main/cpp/src/JNI_RTCRtpSender.cpp deleted file mode 100644 index 2899121..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_RTCRtpSender.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_RTCRtpSender.h" -#include "api/RTCRtpSendParameters.h" -#include "api/WebRTCUtils.h" -#include "JavaFactories.h" -#include "JavaList.h" -#include "JavaRef.h" -#include "JavaRuntimeException.h" -#include "JavaUtils.h" - -#include "api/RTCDtmfSender.h" -#include "api/rtp_sender_interface.h" - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpSender_getTrack -(JNIEnv * env, jobject caller) -{ - webrtc::RtpSenderInterface * sender = GetHandle(env, caller); - CHECK_HANDLEV(sender, nullptr); - - webrtc::scoped_refptr track = sender->track(); - - if (webrtc::AudioTrackInterface * t = dynamic_cast(track.get())) { - return jni::JavaFactories::create(env, t).release(); - } - else if (webrtc::VideoTrackInterface * t = dynamic_cast(track.get())) { - return jni::JavaFactories::create(env, t).release(); - } - - return nullptr; -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpSender_getTransport -(JNIEnv * env, jobject caller) -{ - webrtc::RtpSenderInterface * sender = GetHandle(env, caller); - CHECK_HANDLEV(sender, nullptr); - - auto transport = sender->dtls_transport(); - - return jni::JavaFactories::create(env, transport.get()).release(); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCRtpSender_replaceTrack -(JNIEnv * env, jobject caller, jobject jTrack) -{ - webrtc::RtpSenderInterface * sender = GetHandle(env, caller); - CHECK_HANDLE(sender); - - webrtc::MediaStreamTrackInterface * track = jTrack == nullptr - ? nullptr - : GetHandle(env, jTrack); - - if (!sender->SetTrack(track)) { - env->Throw(jni::JavaRuntimeException(env, "Set track failed")); - } -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCRtpSender_setParameters -(JNIEnv * env, jobject caller, jobject jParams) -{ - webrtc::RtpSenderInterface * sender = GetHandle(env, caller); - CHECK_HANDLE(sender); - - webrtc::RtpParameters rtp_parameters = jni::RTCRtpSendParameters::toNative(env, jni::JavaLocalRef(env, jParams)); - webrtc::RTCError result = sender->SetParameters(rtp_parameters); - - if (!result.ok()) { - env->Throw(jni::JavaRuntimeException(env, jni::RTCErrorToString(result).c_str())); - } -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpSender_getParameters -(JNIEnv * env, jobject caller) -{ - webrtc::RtpSenderInterface * sender = GetHandle(env, caller); - CHECK_HANDLEV(sender, nullptr); - - return jni::RTCRtpSendParameters::toJava(env, sender->GetParameters()).release(); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCRtpSender_setStreams -(JNIEnv * env, jobject caller, jobject streamIdList) -{ - webrtc::RtpSenderInterface * sender = GetHandle(env, caller); - CHECK_HANDLE(sender); - - std::vector streamIDs = jni::JavaList::toStringVector(env, jni::JavaLocalRef(env, streamIdList)); - - sender->SetStreams(streamIDs); -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpSender_getDtmfSender -(JNIEnv * env, jobject caller) -{ - webrtc::RtpSenderInterface * sender = GetHandle(env, caller); - CHECK_HANDLEV(sender, nullptr); - - auto dtmfSender = sender->GetDtmfSender(); - if (!dtmfSender) { - return nullptr; - } - - auto jDtmfSender = jni::RTCDtmfSender::toJava(env); - - SetHandle(env, jDtmfSender, dtmfSender.get()); - - return jDtmfSender.release(); -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_RTCRtpTransceiver.cpp b/webrtc-jni/src/main/cpp/src/JNI_RTCRtpTransceiver.cpp deleted file mode 100644 index d752bb6..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_RTCRtpTransceiver.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_RTCRtpTransceiver.h" -#include "api/RTCRtpCodecCapability.h" -#include "JavaEnums.h" -#include "JavaError.h" -#include "JavaFactories.h" -#include "JavaList.h" -#include "JavaRef.h" -#include "JavaRuntimeException.h" -#include "JavaString.h" -#include "JavaUtils.h" -#include "WebRTCUtils.h" - -#include "api/rtp_transceiver_interface.h" - -JNIEXPORT jstring JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_getMid -(JNIEnv * env, jobject caller) -{ - webrtc::RtpTransceiverInterface * transceiver = GetHandle(env, caller); - CHECK_HANDLEV(transceiver, nullptr); - - return jni::JavaString::toJava(env, transceiver->mid().value_or("")).release(); -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_getSender -(JNIEnv * env, jobject caller) -{ - webrtc::RtpTransceiverInterface * transceiver = GetHandle(env, caller); - CHECK_HANDLEV(transceiver, nullptr); - - webrtc::scoped_refptr sender = transceiver->sender(); - - return jni::JavaFactories::create(env, sender.get()).release(); -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_getReceiver -(JNIEnv * env, jobject caller) -{ - webrtc::RtpTransceiverInterface * transceiver = GetHandle(env, caller); - CHECK_HANDLEV(transceiver, nullptr); - - webrtc::scoped_refptr receiver = transceiver->receiver(); - - return jni::JavaFactories::create(env, receiver.get()).release(); -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_getDirection -(JNIEnv * env, jobject caller) -{ - webrtc::RtpTransceiverInterface * transceiver = GetHandle(env, caller); - CHECK_HANDLEV(transceiver, nullptr); - - return jni::JavaEnums::toJava(env, transceiver->direction()).release(); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_setDirection -(JNIEnv * env, jobject caller, jobject jDirection) -{ - webrtc::RtpTransceiverInterface * transceiver = GetHandle(env, caller); - CHECK_HANDLE(transceiver); - - webrtc::RTCError result = transceiver->SetDirectionWithError(jni::JavaEnums::toNative(env, jDirection)); - - if (!result.ok()) { - env->Throw(jni::JavaRuntimeException(env, "Set direction failed: %s %s", - ToString(result.type()), result.message())); - } -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_getCurrentDirection -(JNIEnv * env, jobject caller) -{ - webrtc::RtpTransceiverInterface * transceiver = GetHandle(env, caller); - CHECK_HANDLEV(transceiver, nullptr); - - auto directionOpt = transceiver->current_direction(); - - if (!directionOpt.has_value()) { - return nullptr; - } - - return jni::JavaEnums::toJava(env, directionOpt.value()).release(); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_stop -(JNIEnv * env, jobject caller) -{ - webrtc::RtpTransceiverInterface * transceiver = GetHandle(env, caller); - CHECK_HANDLE(transceiver); - - webrtc::RTCError result = transceiver->StopStandard(); - - if (!result.ok()) { - env->Throw(jni::JavaRuntimeException(env, "Stop transceiver failed: %s %s", - ToString(result.type()), result.message())); - } -} - -JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_stopped -(JNIEnv * env, jobject caller) -{ - webrtc::RtpTransceiverInterface * transceiver = GetHandle(env, caller); - CHECK_HANDLEV(transceiver, true); - - return static_cast(transceiver->stopped()); -} - -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_getCodecPreferences -(JNIEnv * env, jobject caller) -{ - webrtc::RtpTransceiverInterface * transceiver = GetHandle(env, caller); - CHECK_HANDLEV(transceiver, nullptr); - - auto capabilities = jni::JavaList::toArrayList(env, transceiver->codec_preferences(), jni::RTCRtpCodecCapability::toJava); - - return capabilities.get(); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCRtpTransceiver_setCodecPreferences -(JNIEnv * env, jobject caller, jobject jPreferences) -{ - webrtc::RtpTransceiverInterface * transceiver = GetHandle(env, caller); - CHECK_HANDLE(transceiver); - - try { - auto ref = jni::JavaLocalRef(env, jPreferences); - auto preferences = jni::JavaList::toVector(env, ref, &jni::RTCRtpCodecCapability::toNative); - - webrtc::RTCError result = transceiver->SetCodecPreferences(preferences); - - if (!result.ok()) { - env->Throw(jni::JavaError(env, "Set codec preferences failed: %s", jni::RTCErrorToString(result).c_str())); - } - } - catch (...) { - ThrowCxxJavaException(env); - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_ScreenCapturer.cpp b/webrtc-jni/src/main/cpp/src/JNI_ScreenCapturer.cpp deleted file mode 100644 index 957292e..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_ScreenCapturer.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_ScreenCapturer.h" -#include "JavaUtils.h" -#include "media/video/desktop/DesktopCapturer.h" - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_desktop_ScreenCapturer_initialize -(JNIEnv * env, jobject caller) -{ - SetHandle(env, caller, new jni::DesktopCapturer(true)); -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_SyncClock.cpp b/webrtc-jni/src/main/cpp/src/JNI_SyncClock.cpp deleted file mode 100644 index 284e76e..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_SyncClock.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_SyncClock.h" -#include "JavaUtils.h" -#include "media/SyncClock.h" - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_SyncClock_initialize -(JNIEnv * env, jobject caller) -{ - jni::SyncClock * clock = new jni::SyncClock(); - - SetHandle(env, caller, clock); -} - -JNIEXPORT jlong JNICALL Java_dev_onvoid_webrtc_media_SyncClock_getTimestampUs -(JNIEnv * env, jobject caller) -{ - jni::SyncClock * clock = GetHandle(env, caller); - CHECK_HANDLEV(clock, 0); - - return clock->GetTimestampUs(); -} - -JNIEXPORT jlong JNICALL Java_dev_onvoid_webrtc_media_SyncClock_getTimestampMs -(JNIEnv * env, jobject caller) -{ - jni::SyncClock * clock = GetHandle(env, caller); - CHECK_HANDLEV(clock, 0); - - return clock->GetTimestampMs(); -} - -JNIEXPORT jlong JNICALL Java_dev_onvoid_webrtc_media_SyncClock_getNtpTime -(JNIEnv * env, jobject caller) -{ - jni::SyncClock * clock = GetHandle(env, caller); - CHECK_HANDLEV(clock, 0); - - webrtc::NtpTime ntpTime = clock->GetNtpTime(); - return ntpTime.ToMs(); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_SyncClock_dispose -(JNIEnv * env, jobject caller) -{ - jni::SyncClock * clock = GetHandle(env, caller); - CHECK_HANDLE(clock); - - delete clock; - - SetHandle(env, caller, nullptr); -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_VideoBufferConverter.cpp b/webrtc-jni/src/main/cpp/src/JNI_VideoBufferConverter.cpp deleted file mode 100644 index 11a684e..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_VideoBufferConverter.cpp +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_VideoBufferConverter.h" -#include "JavaRuntimeException.h" - -#include "api/video/i420_buffer.h" - -#include "libyuv/convert.h" -#include "libyuv/video_common.h" - -size_t CalcBufferSize(int width, int height, int fourCC) { - size_t bufferSize = 0; - - switch (fourCC) { - case libyuv::FOURCC_I420: - case libyuv::FOURCC_NV12: - case libyuv::FOURCC_NV21: - case libyuv::FOURCC_IYUV: - case libyuv::FOURCC_YV12: - bufferSize = width * height + ((width + 1) >> 1) * ((height + 1) >> 1) * 2; - break; - - case libyuv::FOURCC_R444: - case libyuv::FOURCC_RGBP: - case libyuv::FOURCC_RGBO: - case libyuv::FOURCC_YUY2: - case libyuv::FOURCC_UYVY: - bufferSize = width * height * 2; - break; - - case libyuv::FOURCC_24BG: - bufferSize = width * height * 3; - break; - - case libyuv::FOURCC_ARGB: - case libyuv::FOURCC_ABGR: - case libyuv::FOURCC_BGRA: - case libyuv::FOURCC_RGBA: - bufferSize = width * height * 4; - break; - - default: - break; - } - - return bufferSize; -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoBufferConverter_I420toByteArray -(JNIEnv * env, jclass cls, jobject jSrcY, jint srcStrideY, jobject jSrcU, jint srcStrideU, - jobject jSrcV, jint srcStrideV, jbyteArray dst, jint width, jint height, jint fourCC) -{ - jsize arrayLength = env->GetArrayLength(dst); - size_t requiredSize = CalcBufferSize(width, height, fourCC); - - if (arrayLength < requiredSize) { - env->Throw(jni::JavaRuntimeException(env, "Insufficient buffer size [has %d, need %zd]", - arrayLength, requiredSize)); - return; - } - - const uint8_t * srcY = static_cast(env->GetDirectBufferAddress(jSrcY)); - const uint8_t * srcU = static_cast(env->GetDirectBufferAddress(jSrcU)); - const uint8_t * srcV = static_cast(env->GetDirectBufferAddress(jSrcV)); - - jbyte * arrayPtr = env->GetByteArrayElements(dst, nullptr); - uint8_t * dstPtr = reinterpret_cast(arrayPtr); - - const int conversionResult = libyuv::ConvertFromI420(srcY, srcStrideY, srcU, srcStrideU, - srcV, srcStrideV, dstPtr, 0, width, height, static_cast(fourCC)); - - if (conversionResult < 0) { - env->Throw(jni::JavaRuntimeException(env, "Failed to convert buffer to I420: %d", - conversionResult)); - } - else { - env->SetByteArrayRegion(dst, 0, arrayLength, arrayPtr); - } - - env->ReleaseByteArrayElements(dst, arrayPtr, JNI_ABORT); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoBufferConverter_I420toDirectBuffer -(JNIEnv * env, jclass, jobject jSrcY, jint srcStrideY, jobject jSrcU, jint srcStrideU, - jobject jSrcV, jint srcStrideV, jobject dst, jint width, jint height, jint fourCC) -{ - const uint8_t * srcY = static_cast(env->GetDirectBufferAddress(jSrcY)); - const uint8_t * srcU = static_cast(env->GetDirectBufferAddress(jSrcU)); - const uint8_t * srcV = static_cast(env->GetDirectBufferAddress(jSrcV)); - - uint8_t * address = static_cast(env->GetDirectBufferAddress(dst)); - - if (address != NULL) { - size_t bufferLength = env->GetDirectBufferCapacity(dst); - size_t requiredSize = CalcBufferSize(width, height, fourCC); - - if (bufferLength < requiredSize) { - env->Throw(jni::JavaRuntimeException(env, "Insufficient buffer size [has %zd, need %zd]", - bufferLength, requiredSize)); - return; - } - - const int conversionResult = libyuv::ConvertFromI420(srcY, srcStrideY, srcU, srcStrideU, - srcV, srcStrideV, address, 0, width, height, static_cast(fourCC)); - - if (conversionResult < 0) { - env->Throw(jni::JavaRuntimeException(env, "Failed to convert buffer to I420: %d", - conversionResult)); - } - } - else { - env->Throw(jni::JavaRuntimeException(env, "Non-direct buffer provided")); - } -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoBufferConverter_byteArrayToI420 -(JNIEnv * env, jclass cls, jbyteArray src, jint width, jint height, jobject jDstY, jint dstStrideY, - jobject jDstU, jint dstStrideU, jobject jDstV, jint dstStrideV, jint fourCC) -{ - jsize arrayLength = env->GetArrayLength(src); - size_t requiredSize = CalcBufferSize(width, height, fourCC); - - if (arrayLength < requiredSize) { - env->Throw(jni::JavaRuntimeException(env, "Insufficient buffer size [has %d, need %zd]", - arrayLength, requiredSize)); - return; - } - - uint8_t * dstY = static_cast(env->GetDirectBufferAddress(jDstY)); - uint8_t * dstU = static_cast(env->GetDirectBufferAddress(jDstU)); - uint8_t * dstV = static_cast(env->GetDirectBufferAddress(jDstV)); - - jbyte * arrayPtr = env->GetByteArrayElements(src, nullptr); - const uint8_t * srcPtr = reinterpret_cast(arrayPtr); - - const int conversionResult = libyuv::ConvertToI420( - srcPtr, arrayLength, - dstY, dstStrideY, - dstU, dstStrideU, - dstV, dstStrideV, - 0, 0, width, height, width, height, - libyuv::kRotate0, static_cast(fourCC)); - - if (conversionResult < 0) { - env->Throw(jni::JavaRuntimeException(env, "Failed to convert buffer to I420: %d", - conversionResult)); - } - - env->ReleaseByteArrayElements(src, arrayPtr, JNI_ABORT); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoBufferConverter_directBufferToI420 -(JNIEnv * env, jclass, jobject src, jint width, jint height, jobject jDstY, jint dstStrideY, - jobject jDstU, jint dstStrideU, jobject jDstV, jint dstStrideV, jint fourCC) -{ - uint8_t * dstY = static_cast(env->GetDirectBufferAddress(jDstY)); - uint8_t * dstU = static_cast(env->GetDirectBufferAddress(jDstU)); - uint8_t * dstV = static_cast(env->GetDirectBufferAddress(jDstV)); - - const uint8_t * address = static_cast(env->GetDirectBufferAddress(src)); - - if (address != NULL) { - size_t bufferLength = env->GetDirectBufferCapacity(src); - size_t requiredSize = CalcBufferSize(width, height, fourCC); - - if (bufferLength < requiredSize) { - env->Throw(jni::JavaRuntimeException(env, "Insufficient buffer size [has %zd, need %zd]", - bufferLength, requiredSize)); - return; - } - - const int conversionResult = libyuv::ConvertToI420( - address, bufferLength, - dstY, dstStrideY, - dstU, dstStrideU, - dstV, dstStrideV, - 0, 0, width, height, width, height, - libyuv::kRotate0, static_cast(fourCC)); - - if (conversionResult < 0) { - env->Throw(jni::JavaRuntimeException(env, "Failed to convert buffer to I420: %d", - conversionResult)); - } - } - else { - env->Throw(jni::JavaRuntimeException(env, "Non-direct buffer provided")); - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_VideoCapture.cpp b/webrtc-jni/src/main/cpp/src/JNI_VideoCapture.cpp deleted file mode 100644 index 287c353..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_VideoCapture.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_VideoCapture.h" -#include "api/VideoTrackSink.h" -#include "media/video/VideoCapture.h" -#include "media/video/VideoDevice.h" -#include "JavaRef.h" -#include "JavaObject.h" -#include "JavaString.h" -#include "JavaUtils.h" - -#ifdef __APPLE__ -#include "media/video/macos/VideoCaptureMac.h" -#endif - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoCapture_setVideoCaptureDevice -(JNIEnv * env, jobject caller, jobject device) -{ - if (!device) { - env->Throw(jni::JavaNullPointerException(env, "VideoDevice is null")); - return; - } - - jni::VideoCaptureBase * videoSource = GetHandle(env, caller); - CHECK_HANDLE(videoSource); - - const auto dev = jni::VideoDevice::toNativeVideoDevice(env, jni::JavaLocalRef(env, device)); - - videoSource->setDevice(std::make_shared(dev.getName(), dev.getDescriptor())); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoCapture_setVideoCaptureCapability -(JNIEnv * env, jobject caller, jobject jcapability) -{ - jni::VideoCaptureBase * videoSource = GetHandle(env, caller); - CHECK_HANDLE(videoSource); - - if (!jcapability) { - env->Throw(jni::JavaNullPointerException(env, "VideoCaptureCapability is null")); - return; - } - - jint width = env->GetIntField(jcapability, GetFieldID(env, jcapability, "width", "I")); - jint height = env->GetIntField(jcapability, GetFieldID(env, jcapability, "height", "I")); - jint frameRate = env->GetIntField(jcapability, GetFieldID(env, jcapability, "frameRate", "I")); - - webrtc::VideoCaptureCapability capability; - capability.width = static_cast(width); - capability.height = static_cast(height); - capability.maxFPS = static_cast(frameRate); - - videoSource->setVideoCaptureCapability(capability); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoCapture_setVideoSink -(JNIEnv * env, jobject caller, jobject jsink) -{ - if (jsink == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "VideoTrackSink must not be null")); - return; - } - - jni::VideoCaptureBase * videoSource = GetHandle(env, caller); - CHECK_HANDLE(videoSource); - - videoSource->setVideoSink(std::make_unique(env, jni::JavaGlobalRef(env, jsink))); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoCapture_start -(JNIEnv * env, jobject caller) -{ - jni::VideoCaptureBase * videoSource = GetHandle(env, caller); - CHECK_HANDLE(videoSource); - - try { - videoSource->start(); - } - catch (...) { - ThrowCxxJavaException(env); - } -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoCapture_stop -(JNIEnv * env, jobject caller) -{ - jni::VideoCaptureBase * videoSource = GetHandle(env, caller); - CHECK_HANDLE(videoSource); - - try { - videoSource->stop(); - } - catch (...) { - ThrowCxxJavaException(env); - } -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoCapture_dispose -(JNIEnv * env, jobject caller) -{ - jni::VideoCaptureBase * videoSource = GetHandle(env, caller); - CHECK_HANDLE(videoSource); - - SetHandle(env, caller, nullptr); - - videoSource = nullptr; -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoCapture_initialize -(JNIEnv * env, jobject caller) -{ -#ifdef __APPLE__ - SetHandle(env, caller, new jni::VideoCaptureMac()); -#else - SetHandle(env, caller, new jni::VideoCapture()); -#endif -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_VideoDesktopSource.cpp b/webrtc-jni/src/main/cpp/src/JNI_VideoDesktopSource.cpp deleted file mode 100644 index 2dfb04d..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_VideoDesktopSource.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_VideoDesktopSource.h" -#include "api/VideoTrackSink.h" -#include "media/video/VideoTrackDesktopSource.h" -#include "JavaRef.h" -#include "JavaObject.h" -#include "JavaString.h" -#include "JavaUtils.h" -#include "rtc_base/logging.h" -#include "rtc_base/ref_counted_object.h" - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDesktopSource_setSourceId -(JNIEnv * env, jobject caller, jlong sourceId, jboolean isWindow) -{ - jni::VideoTrackDesktopSource * videoSource = GetHandle(env, caller); - CHECK_HANDLE(videoSource); - - videoSource->setSourceId(static_cast(sourceId), static_cast(isWindow)); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDesktopSource_setFrameRate -(JNIEnv * env, jobject caller, jint frameRate) -{ - jni::VideoTrackDesktopSource * videoSource = GetHandle(env, caller); - CHECK_HANDLE(videoSource); - - videoSource->setFrameRate(static_cast(frameRate)); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDesktopSource_setMaxFrameSize -(JNIEnv* env, jobject caller, jint width, jint height) -{ - jni::VideoTrackDesktopSource * videoSource = GetHandle(env, caller); - CHECK_HANDLE(videoSource); - - videoSource->setMaxFrameSize(webrtc::DesktopSize(width, height)); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDesktopSource_setFocusSelectedSource -(JNIEnv * env, jobject caller, jboolean focus) -{ - jni::VideoTrackDesktopSource * videoSource = GetHandle(env, caller); - CHECK_HANDLE(videoSource); - - videoSource->setFocusSelectedSource(focus); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDesktopSource_start -(JNIEnv * env, jobject caller) -{ - jni::VideoTrackDesktopSource * videoSource = GetHandle(env, caller); - CHECK_HANDLE(videoSource); - - try { - videoSource->start(); - } - catch (...) { - ThrowCxxJavaException(env); - } -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDesktopSource_stop -(JNIEnv * env, jobject caller) -{ - jni::VideoTrackDesktopSource * videoSource = GetHandle(env, caller); - CHECK_HANDLE(videoSource); - - try { - videoSource->stop(); - } - catch (...) { - ThrowCxxJavaException(env); - } -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDesktopSource_dispose -(JNIEnv * env, jobject caller) -{ - jni::VideoTrackDesktopSource * videoSource = GetHandle(env, caller); - CHECK_HANDLE(videoSource); - - webrtc::RefCountReleaseStatus status = videoSource->Release(); - - if (status != webrtc::RefCountReleaseStatus::kDroppedLastRef) { - RTC_LOG(LS_WARNING) << "Native object was not deleted. A reference is still around somewhere."; - } - - SetHandle(env, caller, nullptr); - - videoSource = nullptr; -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDesktopSource_initialize -(JNIEnv * env, jobject caller) -{ - webrtc::scoped_refptr videoSource = webrtc::make_ref_counted(); - - SetHandle(env, caller, videoSource.release()); -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_VideoDeviceSource.cpp b/webrtc-jni/src/main/cpp/src/JNI_VideoDeviceSource.cpp deleted file mode 100644 index 3e29063..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_VideoDeviceSource.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_VideoDeviceSource.h" -#include "api/VideoTrackSink.h" -#include "media/video/VideoDevice.h" -#include "media/video/VideoTrackDeviceSource.h" -#include "media/video/VideoTrackDeviceSourceBase.h" - -#ifdef __APPLE__ -#include "media/video/macos/VideoTrackDeviceSourceMac.h" -#endif - -#include "JavaRef.h" -#include "JavaObject.h" -#include "JavaString.h" -#include "JavaUtils.h" - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDeviceSource_setVideoCaptureDevice -(JNIEnv * env, jobject caller, jobject device) -{ - if (!device) { - env->Throw(jni::JavaNullPointerException(env, "VideoDevice is null")); - return; - } - -#ifdef __APPLE__ - jni::VideoTrackDeviceSourceMac * videoSource = GetHandle(env, caller); -#else - jni::VideoTrackDeviceSource * videoSource = GetHandle(env, caller); -#endif - - CHECK_HANDLE(videoSource); - - const auto dev = jni::VideoDevice::toNativeVideoDevice(env, jni::JavaLocalRef(env, device)); - - videoSource->setVideoDevice(std::make_shared(dev.getName(), dev.getDescriptor())); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDeviceSource_setVideoCaptureCapability -(JNIEnv * env, jobject caller, jobject jcapability) -{ -#ifdef __APPLE__ - jni::VideoTrackDeviceSourceMac * videoSource = GetHandle(env, caller); -#else - jni::VideoTrackDeviceSource * videoSource = GetHandle(env, caller); -#endif - - CHECK_HANDLE(videoSource); - - if (!jcapability) { - env->Throw(jni::JavaNullPointerException(env, "VideoCaptureCapability is null")); - return; - } - - jint width = env->GetIntField(jcapability, GetFieldID(env, jcapability, "width", "I")); - jint height = env->GetIntField(jcapability, GetFieldID(env, jcapability, "height", "I")); - jint frameRate = env->GetIntField(jcapability, GetFieldID(env, jcapability, "frameRate", "I")); - - webrtc::VideoCaptureCapability capability; - capability.width = static_cast(width); - capability.height = static_cast(height); - capability.maxFPS = static_cast(frameRate); - - videoSource->setVideoCaptureCapability(capability); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDeviceSource_start -(JNIEnv * env, jobject caller) -{ -#ifdef __APPLE__ - jni::VideoTrackDeviceSourceMac * videoSource = GetHandle(env, caller); -#else - jni::VideoTrackDeviceSource * videoSource = GetHandle(env, caller); -#endif - - CHECK_HANDLE(videoSource); - - try { - videoSource->start(); - } - catch (...) { - ThrowCxxJavaException(env); - } -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDeviceSource_stop -(JNIEnv * env, jobject caller) -{ -#ifdef __APPLE__ - jni::VideoTrackDeviceSourceMac * videoSource = GetHandle(env, caller); -#else - jni::VideoTrackDeviceSource * videoSource = GetHandle(env, caller); -#endif - - CHECK_HANDLE(videoSource); - - try { - videoSource->stop(); - } - catch (...) { - ThrowCxxJavaException(env); - } -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDeviceSource_dispose -(JNIEnv * env, jobject caller) -{ -#ifdef __APPLE__ - jni::VideoTrackDeviceSourceMac * videoSource = GetHandle(env, caller); -#else - jni::VideoTrackDeviceSource * videoSource = GetHandle(env, caller); -#endif - - CHECK_HANDLE(videoSource); - - webrtc::RefCountReleaseStatus status = videoSource->Release(); - - if (status != webrtc::RefCountReleaseStatus::kDroppedLastRef) { - RTC_LOG(LS_WARNING) << "Native object was not deleted. A reference is still around somewhere."; - } - - SetHandle(env, caller, nullptr); - - videoSource = nullptr; -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoDeviceSource_initialize -(JNIEnv * env, jobject caller) -{ -#ifdef __APPLE__ - webrtc::scoped_refptr videoSource_ = webrtc::make_ref_counted(); - SetHandle(env, caller, videoSource_.release()); -#else - webrtc::scoped_refptr videoSource = webrtc::make_ref_counted(); - SetHandle(env, caller, videoSource.release()); -#endif -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_VideoTrack.cpp b/webrtc-jni/src/main/cpp/src/JNI_VideoTrack.cpp deleted file mode 100644 index 95bc599..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_VideoTrack.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_VideoTrack.h" -#include "api/VideoTrackSink.h" -#include "JavaNullPointerException.h" -#include "JavaUtils.h" - -#include "api/media_stream_interface.h" - -JNIEXPORT jlong JNICALL Java_dev_onvoid_webrtc_media_video_VideoTrack_addSinkInternal -(JNIEnv * env, jobject caller, jobject jsink) -{ - if (jsink == nullptr) { - env->Throw(jni::JavaNullPointerException(env, "VideoTrackSink must not be null")); - return 0; - } - - webrtc::VideoTrackInterface * track = GetHandle(env, caller); - CHECK_HANDLEV(track, 0); - - auto sink = new jni::VideoTrackSink(env, jni::JavaGlobalRef(env, jsink)); - - track->AddOrUpdateSink(sink, webrtc::VideoSinkWants()); - - return reinterpret_cast(sink); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoTrack_removeSinkInternal -(JNIEnv * env, jobject caller, jlong sinkHandle) -{ - webrtc::VideoTrackInterface * track = GetHandle(env, caller); - CHECK_HANDLE(track); - - auto sink = reinterpret_cast *>(sinkHandle); - - if (sink != nullptr) { - track->RemoveSink(sink); - - delete sink; - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_VoiceActivityDetector.cpp b/webrtc-jni/src/main/cpp/src/JNI_VoiceActivityDetector.cpp deleted file mode 100644 index c62b594..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_VoiceActivityDetector.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_VoiceActivityDetector.h" - -#include "JavaObject.h" -#include "JavaUtils.h" - -#include "modules/audio_processing/vad/voice_activity_detector.h" - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_VoiceActivityDetector_process -(JNIEnv * env, jobject caller, jbyteArray data, jint sampleCount, jint sampleRate) -{ - webrtc::VoiceActivityDetector * activityDetector = GetHandle(env, caller); - CHECK_HANDLE(activityDetector); - - jbyte * dataPtr = env->GetByteArrayElements(data, nullptr); - const int16_t * data16Ptr = reinterpret_cast(dataPtr); - - activityDetector->ProcessChunk(data16Ptr, sampleCount, sampleRate); - - env->ReleaseByteArrayElements(data, dataPtr, JNI_ABORT); -} - -JNIEXPORT jfloat JNICALL Java_dev_onvoid_webrtc_media_audio_VoiceActivityDetector_getLastVoiceProbability -(JNIEnv * env, jobject caller) -{ - webrtc::VoiceActivityDetector * activityDetector = GetHandle(env, caller); - CHECK_HANDLEV(activityDetector, 0); - - return activityDetector->last_voice_probability(); -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_VoiceActivityDetector_dispose -(JNIEnv * env, jobject caller) -{ - webrtc::VoiceActivityDetector * activityDetector = GetHandle(env, caller); - CHECK_HANDLE(activityDetector); - - SetHandle(env, caller, nullptr); - - delete activityDetector; -} - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_audio_VoiceActivityDetector_initialize -(JNIEnv * env, jobject caller) -{ - webrtc::VoiceActivityDetector * activityDetector = new webrtc::VoiceActivityDetector(); - - SetHandle(env, caller, activityDetector); -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_WindowCapturer.cpp b/webrtc-jni/src/main/cpp/src/JNI_WindowCapturer.cpp deleted file mode 100644 index c08107b..0000000 --- a/webrtc-jni/src/main/cpp/src/JNI_WindowCapturer.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "JNI_WindowCapturer.h" -#include "JavaUtils.h" -#include "media/video/desktop/DesktopCapturer.h" - -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_desktop_WindowCapturer_initialize -(JNIEnv * env, jobject caller) -{ - SetHandle(env, caller, new jni::DesktopCapturer(false)); -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/WebRTCContext.cpp b/webrtc-jni/src/main/cpp/src/WebRTCContext.cpp index 165411e..7d66beb 100644 --- a/webrtc-jni/src/main/cpp/src/WebRTCContext.cpp +++ b/webrtc-jni/src/main/cpp/src/WebRTCContext.cpp @@ -27,36 +27,15 @@ #include "api/environment/environment_factory.h" #include "api/peer_connection_interface.h" -#include "modules/desktop_capture/desktop_capturer.h" #include "rtc_base/ssl_adapter.h" -#ifdef _WIN32 -#include -#include "media/audio/windows/WindowsAudioDeviceManager.h" -#include "media/video/windows/WindowsVideoDeviceManager.h" -#include "media/video/desktop/windows/WindowsPowerManagement.h" -#endif -#ifdef __linux__ -#include "media/audio/linux/PulseAudioDeviceManager.h" -#include "media/video/linux/V4l2VideoDeviceManager.h" -#include "media/video/desktop/linux/LinuxPowerManagement.h" -#endif -#ifdef __APPLE__ -#include "media/audio/macos/CoreAudioDeviceManager.h" -#include "media/video/macos/AVFVideoDeviceManager.h" -#include "media/video/desktop/macos/MacOSPowerManagement.h" -#endif - #include namespace jni { WebRTCContext::WebRTCContext(JavaVM * vm) : JavaContext(vm), - webrtcEnv(webrtc::CreateEnvironment()), - audioDevManager(nullptr), - videoDevManager(nullptr), - powerManagement(nullptr) + webrtcEnv(webrtc::CreateEnvironment()) { } @@ -72,8 +51,6 @@ namespace jni JavaEnums::add(env, PKG_DESKTOP"DesktopCapturer$Result"); JavaEnums::add(env, PKG"RTCDtlsTransportState"); JavaEnums::add(env, PKG"RTCDtxStatus"); - JavaEnums::add(env, PKG_MEDIA"MediaSource$State"); - JavaEnums::add(env, PKG_MEDIA"MediaStreamTrackState"); JavaEnums::add(env, PKG"RTCBundlePolicy"); JavaEnums::add(env, PKG"RTCIceConnectionState"); JavaEnums::add(env, PKG"RTCIceGatheringState"); @@ -82,29 +59,13 @@ namespace jni JavaEnums::add(env, PKG"RTCRtcpMuxPolicy"); JavaEnums::add(env, PKG"RTCSignalingState"); JavaEnums::add(env, PKG"TlsCertPolicy"); - JavaEnums::add(env, PKG"RTCRtpTransceiverDirection"); JavaEnums::add(env, PKG"RTCSdpType"); - JavaEnums::add(env, PKG_AUDIO"AudioLayer"); - JavaEnums::add(env, PKG_AUDIO"AudioProcessingConfig$GainController$Mode"); - JavaEnums::add(env, PKG_AUDIO"AudioProcessingConfig$GainController$AnalogGainController$ClippingPredictor$Mode"); - JavaEnums::add(env, PKG_AUDIO"AudioProcessingConfig$Pipeline$DownmixMethod"); - JavaEnums::add(env, PKG_AUDIO"AudioProcessingConfig$NoiseSuppression$Level"); JavaEnums::add(env, PKG"RTCStatsType"); - JavaEnums::add(env, PKG_MEDIA"DeviceFormFactor"); - JavaEnums::add(env, PKG_MEDIA"DeviceTransport"); - JavaEnums::add(env, PKG_MEDIA"AudioDeviceDirectionType"); - JavaFactories::add(env, PKG_MEDIA"audio/AudioTrackSource"); - JavaFactories::add(env, PKG_MEDIA"audio/AudioTrack"); - JavaFactories::add(env, PKG_MEDIA"video/VideoTrack"); - JavaFactories::add(env, PKG_MEDIA"MediaStream"); JavaFactories::add(env, PKG"RTCDataChannel"); JavaFactories::add(env, PKG"RTCDtlsTransport"); JavaFactories::add(env, PKG"RTCIceTransport"); JavaFactories::add(env, PKG"RTCPeerConnection"); - JavaFactories::add(env, PKG"RTCRtpReceiver"); - JavaFactories::add(env, PKG"RTCRtpSender"); - JavaFactories::add(env, PKG"RTCRtpTransceiver"); initializeClassLoader(env, PKG_INTERNAL"NativeClassLoader"); } @@ -129,80 +90,5 @@ namespace jni if (!webrtc::CleanupSSL()) { env->Throw(jni::JavaError(env, "Cleanup SSL failed")); } - - audioDevManager = nullptr; - videoDevManager = nullptr; - } - - avdev::AudioDeviceManager * WebRTCContext::getAudioDeviceManager() - { - std::unique_lock mlock(aMutex); - - if (audioDevManager == nullptr) { - initializeAudioManager(); - } - - return audioDevManager.get(); - } - - avdev::VideoDeviceManager * WebRTCContext::getVideoDeviceManager() - { - std::unique_lock mlock(vMutex); - - if (videoDevManager == nullptr) { - initializeVideoManager(); - } - - return videoDevManager.get(); - } - - avdev::PowerManagement * WebRTCContext::getPowerManagement() - { - std::unique_lock mlock(vMutex); - - if (powerManagement == nullptr) { - initializePowerManagement(); - } - - return powerManagement.get(); - } - - void WebRTCContext::initializeAudioManager() - { -#ifdef _WIN32 - audioDevManager = std::make_unique(); -#endif -#ifdef __linux__ - audioDevManager = std::make_unique(); -#endif -#ifdef __APPLE__ - audioDevManager = std::make_unique(); -#endif - } - - void WebRTCContext::initializeVideoManager() - { -#ifdef _WIN32 - videoDevManager = std::make_unique(); -#endif -#ifdef __linux__ - videoDevManager = std::make_unique(); -#endif -#ifdef __APPLE__ - videoDevManager = std::make_unique(); -#endif - } - - void WebRTCContext::initializePowerManagement() - { -#ifdef _WIN32 - powerManagement = std::make_unique(); -#endif -#ifdef __linux__ - powerManagement = std::make_unique(); -#endif -#ifdef __APPLE__ - powerManagement = std::make_unique(); -#endif } } \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/api/AudioOptions.cpp b/webrtc-jni/src/main/cpp/src/api/AudioOptions.cpp deleted file mode 100644 index 64884de..0000000 --- a/webrtc-jni/src/main/cpp/src/api/AudioOptions.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "api/AudioOptions.h" -#include "JavaClasses.h" -#include "JavaObject.h" -#include "JavaUtils.h" -#include "JNI_WebRTC.h" - -namespace jni -{ - namespace AudioOptions - { - webrtc::AudioOptions toNative(JNIEnv * env, const JavaRef& javaType) - { - const auto javaClass = JavaClasses::get(env); - - JavaObject obj(env, javaType); - - auto options = webrtc::AudioOptions(); - options.echo_cancellation = obj.getBoolean(javaClass->echoCancellation); - options.auto_gain_control = obj.getBoolean(javaClass->autoGainControl); - options.noise_suppression = obj.getBoolean(javaClass->noiseSuppression); - options.highpass_filter = obj.getBoolean(javaClass->highpassFilter); - - return options; - } - - JavaAudioOptionsClass::JavaAudioOptionsClass(JNIEnv * env) - { - cls = FindClass(env, PKG_AUDIO"AudioOptions"); - - echoCancellation = GetFieldID(env, cls, "echoCancellation", "Z"); - autoGainControl = GetFieldID(env, cls, "autoGainControl", "Z"); - noiseSuppression = GetFieldID(env, cls, "noiseSuppression", "Z"); - highpassFilter = GetFieldID(env, cls, "highpassFilter", "Z"); - } - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/api/AudioTrackSink.cpp b/webrtc-jni/src/main/cpp/src/api/AudioTrackSink.cpp deleted file mode 100644 index 5470542..0000000 --- a/webrtc-jni/src/main/cpp/src/api/AudioTrackSink.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "api/AudioTrackSink.h" -#include "JavaClasses.h" -#include "JNI_WebRTC.h" - -namespace jni -{ - AudioTrackSink::AudioTrackSink(JNIEnv * env, const JavaGlobalRef & sink) : - sink(sink), - javaClass(JavaClasses::get(env)) - { - } - - void AudioTrackSink::OnData(const void * data, int bitsPerSample, int sampleRate, size_t channels, size_t frames) - { - JNIEnv * env = AttachCurrentThread(); - - const jbyte * buffer = static_cast(data); - jsize dataSize = static_cast(frames * channels * (bitsPerSample / 8)); - - jbyteArray dataArray = env->NewByteArray(dataSize); - env->SetByteArrayRegion(dataArray, 0, dataSize, buffer); - - env->CallVoidMethod(sink, javaClass->onData, dataArray, bitsPerSample, sampleRate, channels, frames); - ExceptionCheck(env); - env->DeleteLocalRef(dataArray); - } - - AudioTrackSink::JavaAudioTrackSinkClass::JavaAudioTrackSinkClass(JNIEnv * env) - { - jclass cls = FindClass(env, PKG_AUDIO"AudioTrackSink"); - - onData = GetMethod(env, cls, "onData", "([BIIII)V"); - } -} diff --git a/webrtc-jni/src/main/cpp/src/api/HeadlessAudioDeviceModule.cpp b/webrtc-jni/src/main/cpp/src/api/HeadlessAudioDeviceModule.cpp deleted file mode 100644 index 83fa9d8..0000000 --- a/webrtc-jni/src/main/cpp/src/api/HeadlessAudioDeviceModule.cpp +++ /dev/null @@ -1,637 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "api/HeadlessAudioDeviceModule.h" - -namespace jni -{ - HeadlessAudioDeviceModule::HeadlessAudioDeviceModule(const webrtc::Environment & env, - int sample_rate_hz, - size_t channels): - sample_rate_hz_(sample_rate_hz), - channels_(channels ? channels : 1), - playoutFramesIn10MS_(0), - recordingFramesIn10MS_(0), - lastCallPlayoutMillis_(0), - lastCallRecordMillis_(0), - audio_callback_(nullptr) - { - audio_device_buffer_ = std::make_unique(&env.task_queue_factory()); - } - - HeadlessAudioDeviceModule::~HeadlessAudioDeviceModule() - { - StopPlayout(); - StopRecording(); - } - - int32_t HeadlessAudioDeviceModule::ActiveAudioLayer(webrtc::AudioDeviceModule::AudioLayer * audioLayer) const - { - if (!audioLayer) { - return -1; - } - *audioLayer = kDummyAudio; - return 0; - } - - int32_t HeadlessAudioDeviceModule::RegisterAudioCallback(webrtc::AudioTransport * audioCallback) - { - webrtc::MutexLock lock(&mutex_); - audio_callback_ = audioCallback; - audio_device_buffer_->RegisterAudioCallback(audioCallback); - return 0; - } - - int32_t HeadlessAudioDeviceModule::Init() - { - initialized_ = true; - return 0; - } - - int32_t HeadlessAudioDeviceModule::Terminate() - { - StopPlayout(); - initialized_ = false; - return 0; - } - - bool HeadlessAudioDeviceModule::Initialized() const - { - return initialized_; - } - - int16_t HeadlessAudioDeviceModule::PlayoutDevices() - { - return 1; - } - - int16_t HeadlessAudioDeviceModule::RecordingDevices() - { - return 1; - } - - int32_t HeadlessAudioDeviceModule::PlayoutDeviceName(uint16_t index, - char name[webrtc::kAdmMaxDeviceNameSize], - char guid[webrtc::kAdmMaxGuidSize]) - { - if (index != 0) { - return -1; - } - - std::snprintf(name, webrtc::kAdmMaxDeviceNameSize, "Virtual Speaker (ADM)"); - std::snprintf(guid, webrtc::kAdmMaxGuidSize, "virtual-speaker"); - - return 0; - } - - int32_t HeadlessAudioDeviceModule::RecordingDeviceName(uint16_t index, - char name[webrtc::kAdmMaxDeviceNameSize], - char guid[webrtc::kAdmMaxGuidSize]) - { - if (index != 0) { - return -1; - } - std::snprintf(name, webrtc::kAdmMaxDeviceNameSize, "Virtual Microphone (ADM)"); - std::snprintf(guid, webrtc::kAdmMaxGuidSize, "virtual-microphone"); - return 0; - } - - int32_t HeadlessAudioDeviceModule::SetPlayoutDevice(uint16_t index) - { - return (index == 0) ? 0 : -1; - } - - int32_t HeadlessAudioDeviceModule::SetPlayoutDevice(WindowsDeviceType /*device*/) - { - return 0; - } - - int32_t HeadlessAudioDeviceModule::SetRecordingDevice(uint16_t index) - { - return (index == 0) ? 0 : -1; - } - - int32_t HeadlessAudioDeviceModule::SetRecordingDevice(WindowsDeviceType /*device*/) - { - return 0; - } - - int32_t HeadlessAudioDeviceModule::PlayoutIsAvailable(bool * available) - { - if (!available) { - return -1; - } - *available = true; - return 0; - } - - int32_t HeadlessAudioDeviceModule::InitPlayout() - { - if (!initialized_) { - return -1; - } - - playoutFramesIn10MS_ = static_cast(sample_rate_hz_ / 100); - - audio_device_buffer_->SetPlayoutSampleRate(static_cast(sample_rate_hz_)); - audio_device_buffer_->SetPlayoutChannels(static_cast(channels_)); - - const size_t total_samples = channels_ * playoutFramesIn10MS_; - if (play_buffer_.size() != total_samples) { - play_buffer_.SetSize(total_samples); - } - - playout_initialized_ = true; - return 0; - } - - bool HeadlessAudioDeviceModule::PlayoutIsInitialized() const - { - return playout_initialized_; - } - - int32_t HeadlessAudioDeviceModule::RecordingIsAvailable(bool * available) - { - if (!available) { - return -1; - } - *available = true; - return 0; - } - - int32_t HeadlessAudioDeviceModule::InitRecording() - { - if (!initialized_) { - return -1; - } - - recordingFramesIn10MS_ = static_cast(sample_rate_hz_ / 100); - - audio_device_buffer_->SetRecordingSampleRate(static_cast(sample_rate_hz_)); - audio_device_buffer_->SetRecordingChannels(static_cast(channels_)); - - const size_t total_samples = channels_ * recordingFramesIn10MS_; - if (record_buffer_.size() != total_samples) { - record_buffer_.SetSize(total_samples); - } - - recording_initialized_ = true; - return 0; - } - - bool HeadlessAudioDeviceModule::RecordingIsInitialized() const - { - return recording_initialized_; - } - - int32_t HeadlessAudioDeviceModule::StartPlayout() - { - if (!initialized_) { - return -1; - } - if (!playout_initialized_) { - return -1; - } - - { - webrtc::MutexLock lock(&mutex_); - if (playing_) { - return 0; // already playing - } - playing_ = true; - audio_device_buffer_->StartPlayout(); - } - - // Launch 10ms render pull thread. - render_thread_ = webrtc::PlatformThread::SpawnJoinable( - [this] { - while (PlayThreadProcess()) { - } - }, - "webrtc_audio_module_play_thread", - webrtc::ThreadAttributes().SetPriority(webrtc::ThreadPriority::kRealtime)); - - return 0; - } - - int32_t HeadlessAudioDeviceModule::StopPlayout() - { - { - webrtc::MutexLock lock(&mutex_); - if (!playing_) { - // Already stopped. - return 0; - } - playing_ = false; - } - - if (!render_thread_.empty()) { - render_thread_.Finalize(); - } - - { - webrtc::MutexLock lock(&mutex_); - audio_device_buffer_->StopPlayout(); - } - return 0; - } - - bool HeadlessAudioDeviceModule::Playing() const - { - return playing_; - } - - int32_t HeadlessAudioDeviceModule::StartRecording() - { - if (!initialized_) { - return -1; - } - if (!recording_initialized_) { - return -1; - } - - { - webrtc::MutexLock lock(&mutex_); - if (recording_) { - return 0; // already recording - } - recording_ = true; - audio_device_buffer_->StartRecording(); - } - - // Launch 10ms capture push thread. - capture_thread_ = webrtc::PlatformThread::SpawnJoinable( - [this] { - while (CaptureThreadProcess()) { - } - }, - "webrtc_audio_module_capture_thread", - webrtc::ThreadAttributes().SetPriority(webrtc::ThreadPriority::kRealtime)); - - return 0; - } - - int32_t HeadlessAudioDeviceModule::StopRecording() - { - { - webrtc::MutexLock lock(&mutex_); - if (!recording_) { - // Already stopped. - return 0; - } - recording_ = false; - } - - if (!capture_thread_.empty()) { - capture_thread_.Finalize(); - } - - { - webrtc::MutexLock lock(&mutex_); - audio_device_buffer_->StopRecording(); - } - return 0; - } - - bool HeadlessAudioDeviceModule::Recording() const - { - return recording_; - } - - int32_t HeadlessAudioDeviceModule::InitSpeaker() - { - return 0; - } - - bool HeadlessAudioDeviceModule::SpeakerIsInitialized() const - { - return true; - } - - int32_t HeadlessAudioDeviceModule::InitMicrophone() - { - return 0; - } - - bool HeadlessAudioDeviceModule::MicrophoneIsInitialized() const - { - return true; - } - - int32_t HeadlessAudioDeviceModule::SpeakerVolumeIsAvailable(bool * available) - { - if (!available) { - return -1; - } - *available = false; - return 0; - } - - int32_t HeadlessAudioDeviceModule::SetSpeakerVolume(uint32_t /*volume*/) - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::SpeakerVolume(uint32_t * /*volume*/) const - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::MaxSpeakerVolume(uint32_t * /*maxVolume*/) const - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::MinSpeakerVolume(uint32_t * /*minVolume*/) const - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::MicrophoneVolumeIsAvailable(bool * available) - { - if (!available) { - return -1; - } - *available = false; - return 0; - } - - int32_t HeadlessAudioDeviceModule::SetMicrophoneVolume(uint32_t /*volume*/) - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::MicrophoneVolume(uint32_t * /*volume*/) const - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::MaxMicrophoneVolume(uint32_t * /*maxVolume*/) const - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::MinMicrophoneVolume(uint32_t * /*minVolume*/) const - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::SpeakerMuteIsAvailable(bool * available) - { - if (!available) { - return -1; - } - *available = false; - return 0; - } - - int32_t HeadlessAudioDeviceModule::SetSpeakerMute(bool /*enable*/) - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::SpeakerMute(bool * /*enabled*/) const - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::MicrophoneMuteIsAvailable(bool * available) - { - if (!available) { - return -1; - } - *available = false; - return 0; - } - - int32_t HeadlessAudioDeviceModule::SetMicrophoneMute(bool /*enable*/) - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::MicrophoneMute(bool * /*enabled*/) const - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::StereoPlayoutIsAvailable(bool * available) const - { - if (!available) { - return -1; - } - *available = (channels_ >= 2); - return 0; - } - - int32_t HeadlessAudioDeviceModule::SetStereoPlayout(bool enable) - { - if (playout_initialized_) { - return -1; - } - - channels_ = enable ? 2u : 1u; - // Propagate channel change to AudioDeviceBuffer if playout is initialized. - webrtc::MutexLock lock(&mutex_); - - const size_t total_samples = channels_ * playoutFramesIn10MS_; - if (play_buffer_.size() != total_samples) { - play_buffer_.SetSize(total_samples); - } - - audio_device_buffer_->SetPlayoutChannels(static_cast(channels_)); - return 0; - } - - int32_t HeadlessAudioDeviceModule::StereoPlayout(bool * enabled) const - { - if (!enabled) { - return -1; - } - *enabled = (channels_ >= 2); - return 0; - } - - int32_t HeadlessAudioDeviceModule::StereoRecordingIsAvailable(bool * available) const - { - if (!available) { - return -1; - } - *available = (channels_ >= 2); - return 0; - } - - int32_t HeadlessAudioDeviceModule::SetStereoRecording(bool enable) - { - if (recording_initialized_) { - return -1; - } - channels_ = enable ? 2u : 1u; - webrtc::MutexLock lock(&mutex_); - const size_t total_samples = channels_ * recordingFramesIn10MS_; - if (record_buffer_.size() != total_samples) { - record_buffer_.SetSize(total_samples); - } - audio_device_buffer_->SetRecordingChannels(static_cast(channels_)); - return 0; - } - - int32_t HeadlessAudioDeviceModule::StereoRecording(bool * enabled) const - { - if (!enabled) { - return -1; - } - *enabled = (channels_ >= 2); - return 0; - } - - int32_t HeadlessAudioDeviceModule::PlayoutDelay(uint16_t * delayMS) const - { - if (!delayMS) { - return -1; - } - *delayMS = 50; // arbitrary nominal - return 0; - } - - bool HeadlessAudioDeviceModule::BuiltInAECIsAvailable() const - { - return false; - } - - bool HeadlessAudioDeviceModule::BuiltInAGCIsAvailable() const - { - return false; - } - - bool HeadlessAudioDeviceModule::BuiltInNSIsAvailable() const - { - return false; - } - - int32_t HeadlessAudioDeviceModule::EnableBuiltInAEC(bool /*enable*/) - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::EnableBuiltInAGC(bool /*enable*/) - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::EnableBuiltInNS(bool /*enable*/) - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::GetPlayoutUnderrunCount() const - { - return 0; - } - - bool HeadlessAudioDeviceModule::PlayThreadProcess() - { - { - webrtc::MutexLock lock(&mutex_); - if (!playing_) { - return false; - } - } - - int64_t currentTime = webrtc::TimeMillis(); - mutex_.Lock(); - - if (lastCallPlayoutMillis_ == 0 || currentTime - lastCallPlayoutMillis_ >= 10) { - mutex_.Unlock(); - audio_device_buffer_->RequestPlayoutData(playoutFramesIn10MS_); - mutex_.Lock(); - - audio_device_buffer_->GetPlayoutData(play_buffer_.data()); - - lastCallPlayoutMillis_ = currentTime; - } - - mutex_.Unlock(); - - int64_t deltaTimeMillis = webrtc::TimeMillis() - currentTime; - - if (deltaTimeMillis < 10) { - webrtc::Thread::SleepMs(10 - deltaTimeMillis); - } - - return true; - } - - bool HeadlessAudioDeviceModule::CaptureThreadProcess() - { - webrtc::AudioTransport* callback = nullptr; - { - webrtc::MutexLock lock(&mutex_); - if (!recording_) { - return false; - } - callback = audio_callback_; - } - - int64_t currentTime = webrtc::TimeMillis(); - mutex_.Lock(); - - if (lastCallRecordMillis_ == 0 || currentTime - lastCallRecordMillis_ >= 10) { - size_t nSamplesOut = 0; - const size_t nBytesPerSample = sizeof(int16_t); - const size_t nChannels = channels_; - const uint32_t samplesPerSec = static_cast(sample_rate_hz_); - int64_t elapsed_time_ms = 0; - int64_t ntp_time_ms = 0; - - if (callback) { - // Pull 10 ms of audio from the registered AudioTransport (Java AudioSource). - callback->NeedMorePlayData(recordingFramesIn10MS_ * nChannels, - nBytesPerSample, - nChannels, - samplesPerSec, - record_buffer_.data(), - nSamplesOut, - &elapsed_time_ms, - &ntp_time_ms); - } - else { - nSamplesOut = recordingFramesIn10MS_ * nChannels; - std::memset(record_buffer_.data(), 0, nSamplesOut * nBytesPerSample); - } - - if (nChannels > 0) { - // Feed the captured buffer to WebRTC. - audio_device_buffer_->SetRecordedBuffer(record_buffer_.data(), recordingFramesIn10MS_); - audio_device_buffer_->SetVQEData(/*play_delay_ms*/ 0, /*rec_delay_ms*/ 0); - - lastCallRecordMillis_ = currentTime; - - mutex_.Unlock(); - audio_device_buffer_->DeliverRecordedData(); - mutex_.Lock(); - } - } - - mutex_.Unlock(); - - int64_t deltaTimeMillis = webrtc::TimeMillis() - currentTime; - if (deltaTimeMillis < 10) { - webrtc::Thread::SleepMs(10 - deltaTimeMillis); - } - - return true; - } -} diff --git a/webrtc-jni/src/main/cpp/src/api/PeerConnectionObserver.cpp b/webrtc-jni/src/main/cpp/src/api/PeerConnectionObserver.cpp index 576aa0e..c1b7b56 100644 --- a/webrtc-jni/src/main/cpp/src/api/PeerConnectionObserver.cpp +++ b/webrtc-jni/src/main/cpp/src/api/PeerConnectionObserver.cpp @@ -57,48 +57,6 @@ namespace jni ExceptionCheck(env); } - void PeerConnectionObserver::OnTrack(webrtc::scoped_refptr transceiver) - { - JNIEnv * env = AttachCurrentThread(); - - auto jTransceiver = JavaFactories::create(env, transceiver.get()); - - env->CallVoidMethod(observer, javaClass->onTrack, jTransceiver.get()); - - ExceptionCheck(env); - } - - void PeerConnectionObserver::OnAddTrack(webrtc::scoped_refptr receiver, const std::vector> & streams) - { - JNIEnv * env = AttachCurrentThread(); - - JavaLocalRef streamArray; - - try { - streamArray = createObjectArray(env, streams); - - auto jReceiver = JavaFactories::create(env, receiver.get()); - - env->CallVoidMethod(observer, javaClass->onAddTrack, jReceiver.get(), streamArray.get()); - } - catch (...) { - ThrowCxxJavaException(env); - } - - ExceptionCheck(env); - } - - void PeerConnectionObserver::OnRemoveTrack(webrtc::scoped_refptr receiver) - { - JNIEnv * env = AttachCurrentThread(); - - auto jReceiver = JavaFactories::create(env, receiver.get()); - - env->CallVoidMethod(observer, javaClass->onRemoveTrack, jReceiver.get()); - - ExceptionCheck(env); - } - void PeerConnectionObserver::OnDataChannel(webrtc::scoped_refptr channel) { JNIEnv * env = AttachCurrentThread(); @@ -199,9 +157,6 @@ namespace jni onConnectionChange = GetMethod(env, cls, "onConnectionChange", "(L" PKG "RTCPeerConnectionState;)V"); onSignalingChange = GetMethod(env, cls, "onSignalingChange", "(L" PKG "RTCSignalingState;)V"); - onTrack = GetMethod(env, cls, "onTrack", "(L" PKG "RTCRtpTransceiver;)V"); - onAddTrack = GetMethod(env, cls, "onAddTrack", "(L" PKG "RTCRtpReceiver;[L" PKG_MEDIA "MediaStream;)V"); - onRemoveTrack = GetMethod(env, cls, "onRemoveTrack", "(L" PKG "RTCRtpReceiver;)V"); onDataChannel = GetMethod(env, cls, "onDataChannel", "(L" PKG "RTCDataChannel;)V"); onRenegotiationNeeded = GetMethod(env, cls, "onRenegotiationNeeded", "()V"); onIceConnectionChange = GetMethod(env, cls, "onIceConnectionChange", "(L" PKG "RTCIceConnectionState;)V"); diff --git a/webrtc-jni/src/main/cpp/src/api/RTCDtmfSender.cpp b/webrtc-jni/src/main/cpp/src/api/RTCDtmfSender.cpp deleted file mode 100644 index 8f27543..0000000 --- a/webrtc-jni/src/main/cpp/src/api/RTCDtmfSender.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "api/RTCDtmfSender.h" -#include "JavaClasses.h" -#include "JavaObject.h" -#include "JavaUtils.h" -#include "JNI_WebRTC.h" - -namespace jni -{ - namespace RTCDtmfSender - { - JavaLocalRef toJava(JNIEnv * env) - { - const auto javaClass = JavaClasses::get(env); - - jobject jDtmfSender = env->NewObject(javaClass->cls, javaClass->ctor); - - return JavaLocalRef(env, jDtmfSender); - } - - JavaRTCDtmfSenderClass::JavaRTCDtmfSenderClass(JNIEnv * env) - { - cls = FindClass(env, PKG"RTCDtmfSender"); - - ctor = GetMethod(env, cls, "", "()V"); - } - } -} diff --git a/webrtc-jni/src/main/cpp/src/api/RTCDtmfSenderObserver.cpp b/webrtc-jni/src/main/cpp/src/api/RTCDtmfSenderObserver.cpp deleted file mode 100644 index 92cc998..0000000 --- a/webrtc-jni/src/main/cpp/src/api/RTCDtmfSenderObserver.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "api/RTCDtmfSenderObserver.h" -#include "JavaClasses.h" -#include "JavaString.h" -#include "JavaUtils.h" -#include "JNI_WebRTC.h" - -namespace jni -{ - RTCDtmfSenderObserver::RTCDtmfSenderObserver(JNIEnv * env, const JavaGlobalRef & observer) : - observer(observer), - javaClass(JavaClasses::get(env)) - { - } - - void RTCDtmfSenderObserver::OnToneChange(const std::string & tone, const std::string & tone_buffer) - { - JNIEnv * env = AttachCurrentThread(); - - JavaLocalRef jTone = JavaString::toJava(env, tone); - JavaLocalRef jToneBuffer = JavaString::toJava(env, tone_buffer); - - env->CallVoidMethod(observer, javaClass->onToneChange, jTone.get(), jToneBuffer.get()); - - ExceptionCheck(env); - } - - RTCDtmfSenderObserver::JavaRTCDtmfSenderObserverClass::JavaRTCDtmfSenderObserverClass(JNIEnv * env) - { - jclass cls = FindClass(env, PKG"RTCDtmfSenderObserver"); - - onToneChange = GetMethod(env, cls, "onToneChange", "(Ljava/lang/String;Ljava/lang/String;)V"); - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/api/RTCRtcpParameters.cpp b/webrtc-jni/src/main/cpp/src/api/RTCRtcpParameters.cpp deleted file mode 100644 index 88be722..0000000 --- a/webrtc-jni/src/main/cpp/src/api/RTCRtcpParameters.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "api/RTCRtcpParameters.h" -#include "JavaClasses.h" -#include "JavaObject.h" -#include "JavaString.h" -#include "JavaUtils.h" -#include "JNI_WebRTC.h" - -namespace jni -{ - namespace RTCRtcpParameters - { - JavaLocalRef toJava(JNIEnv * env, const webrtc::RtcpParameters & parameters) - { - const auto javaClass = JavaClasses::get(env); - - JavaLocalRef cName = JavaString::toJava(env, parameters.cname); - jboolean reducedSize = static_cast(parameters.reduced_size); - - jobject object = env->NewObject(javaClass->cls, javaClass->ctor, cName.get(), reducedSize); - ExceptionCheck(env); - - return JavaLocalRef(env, object); - } - - webrtc::RtcpParameters toNative(JNIEnv * env, const JavaRef & parameters) - { - const auto javaClass = JavaClasses::get(env); - - JavaObject obj(env, parameters); - - JavaLocalRef cName = obj.getString(javaClass->cName); - jboolean reducedSize = obj.getBoolean(javaClass->reducedSize); - - webrtc::RtcpParameters params; - params.cname = JavaString::toNative(env, cName); - params.reduced_size = static_cast(reducedSize); - - return params; - } - - JavaRTCRtcpParametersClass::JavaRTCRtcpParametersClass(JNIEnv * env) - { - cls = FindClass(env, PKG"RTCRtcpParameters"); - - ctor = GetMethod(env, cls, "", "(" STRING_SIG "Z)V"); - - cName = GetFieldID(env, cls, "cName", STRING_SIG); - reducedSize = GetFieldID(env, cls, "reducedSize", "Z"); - } - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/api/RTCRtpCapabilities.cpp b/webrtc-jni/src/main/cpp/src/api/RTCRtpCapabilities.cpp deleted file mode 100644 index c2575dd..0000000 --- a/webrtc-jni/src/main/cpp/src/api/RTCRtpCapabilities.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "api/RTCRtpCapabilities.h" -#include "api/RTCRtpCodecCapability.h" -#include "api/RTCRtpHeaderExtensionCapability.h" -#include "JavaArrayList.h" -#include "JavaClasses.h" -#include "JavaList.h" -#include "JavaUtils.h" -#include "JNI_WebRTC.h" - -namespace jni -{ - namespace RTCRtpCapabilities - { - JavaLocalRef toJava(JNIEnv * env, const webrtc::RtpCapabilities & capabilities) - { - const auto javaClass = JavaClasses::get(env); - - JavaLocalRef codecs = JavaList::toArrayList(env, capabilities.codecs, &RTCRtpCodecCapability::toJava); - JavaLocalRef headerExtensions = JavaList::toArrayList(env, capabilities.header_extensions, &RTCRtpHeaderExtensionCapability::toJava); - - jobject object = env->NewObject(javaClass->cls, javaClass->ctor, - codecs.get(), headerExtensions.get()); - - return JavaLocalRef(env, object); - } - - JavaRTCRtpCapabilitiesClass::JavaRTCRtpCapabilitiesClass(JNIEnv * env) - { - cls = FindClass(env, PKG"RTCRtpCapabilities"); - - ctor = GetMethod(env, cls, "", "(" LIST_SIG LIST_SIG ")V"); - } - } -} diff --git a/webrtc-jni/src/main/cpp/src/api/RTCRtpCodecCapability.cpp b/webrtc-jni/src/main/cpp/src/api/RTCRtpCodecCapability.cpp deleted file mode 100644 index b9b386e..0000000 --- a/webrtc-jni/src/main/cpp/src/api/RTCRtpCodecCapability.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "api/RTCRtpCodecCapability.h" -#include "JavaEnums.h" -#include "JavaHashMap.h" -#include "JavaObject.h" -#include "JavaPrimitive.h" -#include "JavaString.h" -#include "JavaUtils.h" -#include "JNI_WebRTC.h" - -namespace jni -{ - namespace RTCRtpCodecCapability - { - JavaLocalRef toJava(JNIEnv * env, const webrtc::RtpCodecCapability & capability) - { - JavaLocalRef mediaType = JavaEnums::toJava(env, capability.kind); - JavaLocalRef codecName = JavaString::toJava(env, capability.name); - JavaLocalRef clockRate = nullptr; - JavaLocalRef channels = nullptr; - - JavaHashMap paramMap(env); - - for (const auto & [p_key, p_value] : capability.parameters) { - JavaLocalRef key = JavaString::toJava(env, p_key); - JavaLocalRef value = JavaString::toJava(env, p_value); - - paramMap.put(key, value); - } - - if (capability.clock_rate.has_value()) { - clockRate = Integer::create(env, capability.clock_rate.value()); - } - if (capability.num_channels.has_value()) { - channels = Integer::create(env, capability.num_channels.value()); - } - - const auto javaClass = JavaClasses::get(env); - - JavaLocalRef fmtMap = paramMap; - - jobject object = env->NewObject(javaClass->cls, javaClass->ctor, - mediaType.get(), codecName.get(), clockRate.get(), channels.get(), fmtMap.get()); - - ExceptionCheck(env); - - return JavaLocalRef(env, object); - } - - webrtc::RtpCodecCapability toNative(JNIEnv * env, const JavaRef & capability) - { - const auto javaClass = JavaClasses::get(env); - - JavaObject obj(env, capability); - - webrtc::RtpCodecCapability codecCapability; - - codecCapability.kind = JavaEnums::toNative(env, obj.getObject(javaClass->mediaType)); - codecCapability.name = JavaString::toNative(env, obj.getString(javaClass->name)); - - for (const auto & entry : JavaHashMap(env, obj.getObject(javaClass->sdpFmtp))) { - std::string key = JavaString::toNative(env, static_java_ref_cast(env, entry.first)); - std::string value = JavaString::toNative(env, static_java_ref_cast(env, entry.second)); - - codecCapability.parameters.emplace(key, value); - } - - auto clockRate = obj.getObject(javaClass->clockRate); - auto channels = obj.getObject(javaClass->channels); - - if (clockRate.get()) { - codecCapability.clock_rate = Integer::getValue(env, clockRate); - } - if (channels.get()) { - codecCapability.num_channels = Integer::getValue(env, channels); - } - - return codecCapability; - } - - JavaRTCRtpCodecCapabilityClass::JavaRTCRtpCodecCapabilityClass(JNIEnv * env) - { - cls = FindClass(env, PKG"RTCRtpCodecCapability"); - - ctor = GetMethod(env, cls, "", "(L" PKG_MEDIA "MediaType;" STRING_SIG INTEGER_SIG INTEGER_SIG MAP_SIG ")V"); - - mediaType = GetFieldID(env, cls, "mediaType", "L" PKG_MEDIA "MediaType;"); - name = GetFieldID(env, cls, "name", STRING_SIG); - clockRate = GetFieldID(env, cls, "clockRate", INTEGER_SIG); - channels = GetFieldID(env, cls, "channels", INTEGER_SIG); - sdpFmtp = GetFieldID(env, cls, "sdpFmtp", MAP_SIG); - } - } -} diff --git a/webrtc-jni/src/main/cpp/src/api/RTCRtpCodecParameters.cpp b/webrtc-jni/src/main/cpp/src/api/RTCRtpCodecParameters.cpp deleted file mode 100644 index c635fc8..0000000 --- a/webrtc-jni/src/main/cpp/src/api/RTCRtpCodecParameters.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "api/RTCRtpCodecParameters.h" -#include "JavaEnums.h" -#include "JavaHashMap.h" -#include "JavaObject.h" -#include "JavaPrimitive.h" -#include "JavaRef.h" -#include "JavaString.h" -#include "JavaUtils.h" -#include "JNI_WebRTC.h" - -namespace jni -{ - namespace RTCRtpCodecParameters - { - JavaLocalRef toJava(JNIEnv * env, const webrtc::RtpCodecParameters & parameters) - { - jint payloadType = static_cast(parameters.payload_type); - JavaLocalRef mediaType = JavaEnums::toJava(env, parameters.kind); - JavaLocalRef codecName = JavaString::toJava(env, parameters.name); - JavaLocalRef clockRate = nullptr; - JavaLocalRef channels = nullptr; - JavaHashMap paramMap(env); - - for (const auto & [p_key, p_value] : parameters.parameters) { - JavaLocalRef key = JavaString::toJava(env, p_key); - JavaLocalRef value = JavaString::toJava(env, p_value); - - paramMap.put(key, value); - } - - if (parameters.clock_rate.has_value()) { - clockRate = Integer::create(env, parameters.clock_rate.value()); - } - if (parameters.num_channels.has_value()) { - channels = Integer::create(env, parameters.num_channels.value()); - } - - const auto javaClass = JavaClasses::get(env); - - jobject object = env->NewObject(javaClass->cls, javaClass->ctor, payloadType, mediaType.get(), codecName.get(), clockRate.get(), channels.get(), ((JavaLocalRef)paramMap).get()); - ExceptionCheck(env); - - return JavaLocalRef(env, object); - } - - webrtc::RtpCodecParameters toNative(JNIEnv * env, const JavaRef & parameters) - { - const auto javaClass = JavaClasses::get(env); - - JavaObject obj(env, parameters); - - webrtc::RtpCodecParameters params; - params.payload_type = obj.getInt(javaClass->payloadType); - params.kind = JavaEnums::toNative(env, obj.getObject(javaClass->mediaType)); - params.name = JavaString::toNative(env, obj.getString(javaClass->codecName)); - - for (const auto & entry : JavaHashMap(env, obj.getObject(javaClass->parameters))) { - std::string key = JavaString::toNative(env, static_java_ref_cast(env, entry.first)); - std::string value = JavaString::toNative(env, static_java_ref_cast(env, entry.second)); - - params.parameters.emplace(key, value); - } - - auto clockRate = obj.getObject(javaClass->clockRate); - auto channels = obj.getObject(javaClass->channels); - - if (clockRate.get()) { - params.clock_rate = Integer::getValue(env, clockRate); - } - if (channels.get()) { - params.num_channels = Integer::getValue(env, channels); - } - - return params; - } - - JavaRTCRtpCodecParametersClass::JavaRTCRtpCodecParametersClass(JNIEnv * env) - { - cls = FindClass(env, PKG"RTCRtpCodecParameters"); - - ctor = GetMethod(env, cls, "", "(IL" PKG_MEDIA "MediaType;" STRING_SIG INTEGER_SIG INTEGER_SIG MAP_SIG ")V"); - - payloadType = GetFieldID(env, cls, "payloadType", "I"); - mediaType = GetFieldID(env, cls, "mediaType", "L" PKG_MEDIA "MediaType;"); - codecName = GetFieldID(env, cls, "codecName", STRING_SIG); - clockRate = GetFieldID(env, cls, "clockRate", INTEGER_SIG); - channels = GetFieldID(env, cls, "channels", INTEGER_SIG); - parameters = GetFieldID(env, cls, "parameters", MAP_SIG); - } - } -} diff --git a/webrtc-jni/src/main/cpp/src/api/RTCRtpContributingSource.cpp b/webrtc-jni/src/main/cpp/src/api/RTCRtpContributingSource.cpp deleted file mode 100644 index 4731621..0000000 --- a/webrtc-jni/src/main/cpp/src/api/RTCRtpContributingSource.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "api/RTCRtpContributingSource.h" -#include "JavaObject.h" -#include "JavaRef.h" -#include "JavaUtils.h" -#include "JNI_WebRTC.h" - -namespace jni -{ - namespace RTCRtpContributingSource - { - JavaLocalRef toJava(JNIEnv * env, const webrtc::RtpSource & source) - { - const auto javaClass = JavaClasses::get(env); - - jlong timestamp = static_cast(source.timestamp().us()); - jlong sourceId = static_cast(source.source_id()); - jdouble audioLevel = static_cast(source.audio_level().value_or(0)); - jlong rtpTimestamp = static_cast(source.rtp_timestamp()); - - jobject object = env->NewObject(javaClass->cls, javaClass->ctor, - timestamp, sourceId, audioLevel, rtpTimestamp); - - return JavaLocalRef(env, object); - } - - webrtc::RtpSource toNative(JNIEnv * env, const JavaRef & source) - { - const auto javaClass = JavaClasses::get(env); - - JavaObject obj(env, source); - - webrtc::RtpSource::Extensions extensions; - extensions.audio_level = static_cast(obj.getDouble(javaClass->audioLevel)); - - return webrtc::RtpSource( - webrtc::Timestamp::Micros(static_cast(obj.getLong(javaClass->timestamp))), - static_cast(obj.getLong(javaClass->sourceId)), - webrtc::RtpSourceType::CSRC, - static_cast(obj.getLong(javaClass->rtpTimestamp)), - extensions - ); - } - - JavaRTCRtpContributingSourceClass::JavaRTCRtpContributingSourceClass(JNIEnv * env) - { - cls = FindClass(env, PKG"RTCRtpContributingSource"); - - ctor = GetMethod(env, cls, "", "(JJDJ)V"); - - timestamp = GetFieldID(env, cls, "timestamp", "J"); - sourceId = GetFieldID(env, cls, "sourceId", "J"); - sourceType = GetFieldID(env, cls, "sourceType", "J"); - audioLevel = GetFieldID(env, cls, "audioLevel", "D"); - rtpTimestamp = GetFieldID(env, cls, "rtpTimestamp", "J"); - } - } -} diff --git a/webrtc-jni/src/main/cpp/src/api/RTCRtpEncodingParameters.cpp b/webrtc-jni/src/main/cpp/src/api/RTCRtpEncodingParameters.cpp deleted file mode 100644 index 4efca12..0000000 --- a/webrtc-jni/src/main/cpp/src/api/RTCRtpEncodingParameters.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "api/RTCRtpEncodingParameters.h" -#include "JavaClasses.h" -#include "JavaEnums.h" -#include "JavaObject.h" -#include "JavaPrimitive.h" -#include "JavaRef.h" -#include "JNI_WebRTC.h" - -namespace jni -{ - namespace RTCRtpEncodingParameters - { - JavaLocalRef toJava(JNIEnv * env, const webrtc::RtpEncodingParameters & parameters) - { - const auto javaClass = JavaClasses::get(env); - - jobject object = env->NewObject(javaClass->cls, javaClass->ctor); - env->SetObjectField(object, javaClass->active, Boolean::create(env, parameters.active)); - - if (parameters.ssrc.has_value()) { - env->SetObjectField(object, javaClass->ssrc, Long::create(env, parameters.ssrc.value())); - } - if (parameters.min_bitrate_bps.has_value()) { - env->SetObjectField(object, javaClass->minBitrate, Integer::create(env, parameters.min_bitrate_bps.value())); - } - if (parameters.max_bitrate_bps.has_value()) { - env->SetObjectField(object, javaClass->maxBitrate, Integer::create(env, parameters.max_bitrate_bps.value())); - } - if (parameters.max_framerate.has_value()) { - env->SetObjectField(object, javaClass->maxFramerate, Double::create(env, parameters.max_framerate.value())); - } - if (parameters.scale_resolution_down_by.has_value()) { - env->SetObjectField(object, javaClass->scaleResolution, Double::create(env, parameters.scale_resolution_down_by.value())); - } - - return JavaLocalRef(env, object); - } - - webrtc::RtpEncodingParameters toNative(JNIEnv * env, const JavaRef & parameters) - { - const auto javaClass = JavaClasses::get(env); - - JavaObject obj(env, parameters); - - auto active = obj.getObject(javaClass->active); - auto ssrc = obj.getObject(javaClass->ssrc); - auto minBitrate = obj.getObject(javaClass->minBitrate); - auto maxBitrate = obj.getObject(javaClass->maxBitrate); - auto maxFramerate = obj.getObject(javaClass->maxFramerate); - auto scaleResolution = obj.getObject(javaClass->scaleResolution); - - webrtc::RtpEncodingParameters params; - - if (active.get()) { - params.active = Boolean::getValue(env, active); - } - if (ssrc.get()) { - params.ssrc = static_cast(Long::getValue(env, ssrc)); - } - if (minBitrate.get()) { - params.min_bitrate_bps.emplace(Integer::getValue(env, minBitrate)); - } - if (maxBitrate.get()) { - params.max_bitrate_bps.emplace(Integer::getValue(env, maxBitrate)); - } - if (maxFramerate.get()) { - params.max_framerate.emplace(Double::getValue(env, maxFramerate)); - } - if (scaleResolution.get()) { - params.scale_resolution_down_by.emplace(Double::getValue(env, scaleResolution)); - } - - return params; - } - - JavaRTCRtpEncodingParametersClass::JavaRTCRtpEncodingParametersClass(JNIEnv * env) - { - cls = FindClass(env, PKG"RTCRtpEncodingParameters"); - - ctor = GetMethod(env, cls, "", "()V"); - - ssrc = GetFieldID(env, cls, "ssrc", LONG_SIG); - active = GetFieldID(env, cls, "active", BOOLEAN_SIG); - minBitrate = GetFieldID(env, cls, "minBitrate", INTEGER_SIG); - maxBitrate = GetFieldID(env, cls, "maxBitrate", INTEGER_SIG); - maxFramerate = GetFieldID(env, cls, "maxFramerate", DOUBLE_SIG); - scaleResolution = GetFieldID(env, cls, "scaleResolutionDownBy", DOUBLE_SIG); - } - } -} diff --git a/webrtc-jni/src/main/cpp/src/api/RTCRtpHeaderExtension.cpp b/webrtc-jni/src/main/cpp/src/api/RTCRtpHeaderExtension.cpp deleted file mode 100644 index 7ad6bfa..0000000 --- a/webrtc-jni/src/main/cpp/src/api/RTCRtpHeaderExtension.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "api/RTCRtpHeaderExtension.h" -#include "JavaClasses.h" -#include "JavaObject.h" -#include "JavaString.h" -#include "JavaUtils.h" -#include "JNI_WebRTC.h" - -namespace jni -{ - namespace RTCRtpHeaderExtension - { - JavaLocalRef toJava(JNIEnv * env, const webrtc::RtpExtension & extension) - { - const auto javaClass = JavaClasses::get(env); - - JavaLocalRef uri = JavaString::toJava(env, extension.uri); - jint id = static_cast(extension.id); - jboolean encrypted = static_cast(extension.encrypt); - - jobject object = env->NewObject(javaClass->cls, javaClass->ctor, uri.get(), id, encrypted); - ExceptionCheck(env); - - return JavaLocalRef(env, object); - } - - webrtc::RtpExtension toNative(JNIEnv * env, const JavaRef & jExtension) - { - const auto javaClass = JavaClasses::get(env); - - JavaObject obj(env, jExtension); - - webrtc::RtpExtension extension; - extension.uri = JavaString::toNative(env, obj.getString(javaClass->uri)); - extension.id = static_cast(obj.getInt(javaClass->id)); - extension.encrypt = static_cast(obj.getBoolean(javaClass->encrypted)); - - return extension; - } - - JavaRTCRtpHeaderExtensionClass::JavaRTCRtpHeaderExtensionClass(JNIEnv * env) - { - cls = FindClass(env, PKG"RTCRtpHeaderExtensionParameters"); - - ctor = GetMethod(env, cls, "", "(" STRING_SIG "IZ)V"); - - uri = GetFieldID(env, cls, "uri", STRING_SIG); - id = GetFieldID(env, cls, "id", "I"); - encrypted = GetFieldID(env, cls, "encrypted", "Z"); - } - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/api/RTCRtpHeaderExtensionCapability.cpp b/webrtc-jni/src/main/cpp/src/api/RTCRtpHeaderExtensionCapability.cpp deleted file mode 100644 index 526e876..0000000 --- a/webrtc-jni/src/main/cpp/src/api/RTCRtpHeaderExtensionCapability.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "api/RTCRtpHeaderExtensionCapability.h" -#include "JavaClasses.h" -#include "JavaObject.h" -#include "JavaString.h" -#include "JavaUtils.h" -#include "JNI_WebRTC.h" - -namespace jni -{ - namespace RTCRtpHeaderExtensionCapability - { - JavaLocalRef toJava(JNIEnv * env, const webrtc::RtpHeaderExtensionCapability & capability) - { - const auto javaClass = JavaClasses::get(env); - - JavaLocalRef uri = JavaString::toJava(env, capability.uri); - - jobject object = env->NewObject(javaClass->cls, javaClass->ctor, uri.get()); - ExceptionCheck(env); - - return JavaLocalRef(env, object); - } - - JavaRTCRtpHeaderExtensionCapabilityClass::JavaRTCRtpHeaderExtensionCapabilityClass(JNIEnv * env) - { - cls = FindClass(env, PKG"RTCRtpHeaderExtensionCapability"); - - ctor = GetMethod(env, cls, "", "(" STRING_SIG ")V"); - } - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/api/RTCRtpParameters.cpp b/webrtc-jni/src/main/cpp/src/api/RTCRtpParameters.cpp deleted file mode 100644 index 53f350f..0000000 --- a/webrtc-jni/src/main/cpp/src/api/RTCRtpParameters.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "api/RTCRtpParameters.h" -#include "api/RTCRtpCodecParameters.h" -#include "api/RTCRtpHeaderExtension.h" -#include "api/RTCRtcpParameters.h" -#include "JavaArrayList.h" -#include "JavaClasses.h" -#include "JavaIterable.h" -#include "JavaList.h" -#include "JavaUtils.h" -#include "JNI_WebRTC.h" - -namespace jni -{ - namespace RTCRtpParameters - { - JavaLocalRef toJava(JNIEnv * env, const webrtc::RtpParameters & parameters) - { - const auto javaClass = JavaClasses::get(env); - - JavaLocalRef rtcp = RTCRtcpParameters::toJava(env, parameters.rtcp); - - jobject object = env->NewObject(javaClass->cls, javaClass->ctor); - env->SetObjectField(object, javaClass->rtcp, rtcp.get()); - env->SetObjectField(object, javaClass->headerExtensions, JavaList::toArrayList(env, parameters.header_extensions, &RTCRtpHeaderExtension::toJava)); - env->SetObjectField(object, javaClass->codecs, JavaList::toArrayList(env, parameters.codecs, &RTCRtpCodecParameters::toJava)); - - return JavaLocalRef(env, object); - } - - webrtc::RtpParameters toNative(JNIEnv * env, const JavaRef & javaType) - { - const auto javaClass = JavaClasses::get(env); - - JavaObject obj(env, javaType); - - JavaLocalRef headerExtensions = obj.getObject(javaClass->headerExtensions); - JavaLocalRef rtcp = obj.getObject(javaClass->rtcp); - JavaLocalRef codecs = obj.getObject(javaClass->codecs); - - webrtc::RtpParameters params; - params.rtcp = RTCRtcpParameters::toNative(env, rtcp); - params.header_extensions = JavaList::toVector(env, headerExtensions, &RTCRtpHeaderExtension::toNative); - params.codecs = JavaList::toVector(env, codecs, &RTCRtpCodecParameters::toNative); - - return params; - } - - JavaRTCRtpParametersClass::JavaRTCRtpParametersClass(JNIEnv * env) - { - cls = FindClass(env, PKG"RTCRtpParameters"); - - ctor = GetMethod(env, cls, "", "()V"); - - headerExtensions = GetFieldID(env, cls, "headerExtensions", LIST_SIG); - rtcp = GetFieldID(env, cls, "rtcp", "L" PKG "RTCRtcpParameters;"); - codecs = GetFieldID(env, cls, "codecs", LIST_SIG); - } - } -} diff --git a/webrtc-jni/src/main/cpp/src/api/RTCRtpSendParameters.cpp b/webrtc-jni/src/main/cpp/src/api/RTCRtpSendParameters.cpp deleted file mode 100644 index 1aadd9d..0000000 --- a/webrtc-jni/src/main/cpp/src/api/RTCRtpSendParameters.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "api/RTCRtpSendParameters.h" -#include "api/RTCRtpCodecParameters.h" -#include "api/RTCRtpEncodingParameters.h" -#include "api/RTCRtpHeaderExtension.h" -#include "api/RTCRtpParameters.h" -#include "api/RTCRtcpParameters.h" -#include "JavaArrayList.h" -#include "JavaClasses.h" -#include "JavaIterable.h" -#include "JavaList.h" -#include "JavaString.h" -#include "JavaUtils.h" -#include "JNI_WebRTC.h" - -namespace jni -{ - namespace RTCRtpSendParameters - { - JavaLocalRef toJava(JNIEnv * env, const webrtc::RtpParameters & parameters) - { - const auto javaClass = JavaClasses::get(env); - const auto javaParentClass = JavaClasses::get(env); - - JavaLocalRef transactionId = JavaString::toJava(env, parameters.transaction_id); - JavaLocalRef rtcp = RTCRtcpParameters::toJava(env, parameters.rtcp); - JavaLocalRef encodings = JavaList::toArrayList(env, parameters.encodings, &RTCRtpEncodingParameters::toJava); - JavaLocalRef headerExtensions = JavaList::toArrayList(env, parameters.header_extensions, &RTCRtpHeaderExtension::toJava); - JavaLocalRef codecs = JavaList::toArrayList(env, parameters.codecs, &RTCRtpCodecParameters::toJava); - - jobject object = env->NewObject(javaClass->cls, javaClass->ctor); - env->SetObjectField(object, javaClass->transactionId, transactionId.get()); - env->SetObjectField(object, javaClass->encodings, encodings.get()); - env->SetObjectField(object, javaParentClass->headerExtensions, headerExtensions.get()); - env->SetObjectField(object, javaParentClass->rtcp, rtcp.get()); - env->SetObjectField(object, javaParentClass->codecs, codecs.get()); - - return JavaLocalRef(env, object); - } - - webrtc::RtpParameters toNative(JNIEnv * env, const JavaRef & parameters) - { - const auto javaClass = JavaClasses::get(env); - const auto javaParentClass = JavaClasses::get(env); - - JavaObject obj(env, parameters); - - JavaLocalRef transactionId = obj.getString(javaClass->transactionId); - JavaLocalRef encodings = obj.getObject(javaClass->encodings); - JavaLocalRef headerExtensions = obj.getObject(javaParentClass->headerExtensions); - JavaLocalRef rtcp = obj.getObject(javaParentClass->rtcp); - JavaLocalRef codecs = obj.getObject(javaParentClass->codecs); - - webrtc::RtpParameters params; - params.transaction_id = JavaString::toNative(env, transactionId); - - if (encodings) { - params.encodings = JavaList::toVector(env, encodings, &RTCRtpEncodingParameters::toNative); - } - if (headerExtensions) { - params.header_extensions = JavaList::toVector(env, headerExtensions, &RTCRtpHeaderExtension::toNative); - } - if (rtcp) { - params.rtcp = RTCRtcpParameters::toNative(env, rtcp); - } - if (codecs) { - params.codecs = JavaList::toVector(env, codecs, &RTCRtpCodecParameters::toNative); - } - - return params; - } - - JavaRTCRtpSendParametersClass::JavaRTCRtpSendParametersClass(JNIEnv * env) - { - cls = FindClass(env, PKG"RTCRtpSendParameters"); - - ctor = GetMethod(env, cls, "", "()V"); - - transactionId = GetFieldID(env, cls, "transactionId", STRING_SIG); - encodings = GetFieldID(env, cls, "encodings", LIST_SIG); - } - } -} diff --git a/webrtc-jni/src/main/cpp/src/api/RTCRtpSynchronizationSource.cpp b/webrtc-jni/src/main/cpp/src/api/RTCRtpSynchronizationSource.cpp deleted file mode 100644 index fc9621b..0000000 --- a/webrtc-jni/src/main/cpp/src/api/RTCRtpSynchronizationSource.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "api/RTCRtpSynchronizationSource.h" -#include "api/RTCRtpContributingSource.h" -#include "JavaObject.h" -#include "JavaRef.h" -#include "JavaUtils.h" -#include "JNI_WebRTC.h" - -namespace jni -{ - namespace RTCRtpSynchronizationSource - { - JavaLocalRef toJava(JNIEnv * env, const webrtc::RtpSource & source) - { - const auto javaClass = JavaClasses::get(env); - - jlong timestamp = static_cast(source.timestamp().us()); - jlong sourceId = static_cast(source.source_id()); - jdouble audioLevel = static_cast(source.audio_level().value_or(0)); - jlong rtpTimestamp = static_cast(source.rtp_timestamp()); - jboolean voiceActivityFlag = false; - - jobject object = env->NewObject(javaClass->cls, javaClass->ctor, - timestamp, sourceId, audioLevel, rtpTimestamp, voiceActivityFlag); - - return JavaLocalRef(env, object); - } - - webrtc::RtpSource toNative(JNIEnv * env, const JavaRef & source) - { - const auto javaClass = JavaClasses::get(env); - const auto parentClass = JavaClasses::get(env); - - JavaObject obj(env, source); - - webrtc::RtpSource::Extensions extensions; - extensions.audio_level = static_cast(obj.getDouble(parentClass->audioLevel)); - - return webrtc::RtpSource( - webrtc::Timestamp::Micros(static_cast(obj.getLong(parentClass->timestamp))), - static_cast(obj.getLong(parentClass->sourceId)), - webrtc::RtpSourceType::SSRC, - static_cast(obj.getLong(parentClass->rtpTimestamp)), - extensions - ); - } - - JavaRTCRtpSynchronizationSourceClass::JavaRTCRtpSynchronizationSourceClass(JNIEnv * env) - { - cls = FindClass(env, PKG"RTCRtpSynchronizationSource"); - - ctor = GetMethod(env, cls, "", "(JJDJZ)V"); - - voiceActivityFlag = GetFieldID(env, cls, "voiceActivityFlag", "Z"); - } - } -} diff --git a/webrtc-jni/src/main/cpp/src/api/RTCRtpTransceiverInit.cpp b/webrtc-jni/src/main/cpp/src/api/RTCRtpTransceiverInit.cpp deleted file mode 100644 index fcddbbb..0000000 --- a/webrtc-jni/src/main/cpp/src/api/RTCRtpTransceiverInit.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "api/RTCRtpTransceiverInit.h" -#include "api/RTCRtpEncodingParameters.h" -#include "JavaClasses.h" -#include "JavaEnums.h" -#include "JavaIterable.h" -#include "JavaList.h" -#include "JavaObject.h" -#include "JavaString.h" -#include "JNI_WebRTC.h" - -namespace jni -{ - namespace RTCRtpTransceiverInit - { - webrtc::RtpTransceiverInit toNative(JNIEnv * env, const JavaRef& javaType) - { - const auto javaClass = JavaClasses::get(env); - - JavaObject obj(env, javaType); - - JavaLocalRef ids = obj.getObject(javaClass->streamIds); - JavaLocalRef encodings = obj.getObject(javaClass->sendEncodings); - - webrtc::RtpTransceiverInit init; - init.direction = JavaEnums::toNative(env, obj.getObject(javaClass->direction)); - init.stream_ids = JavaList::toStringVector(env, ids); - init.send_encodings = JavaList::toVector(env, encodings, &RTCRtpEncodingParameters::toNative); - - return init; - } - - JavaRTCRtpTransceiverInitClass::JavaRTCRtpTransceiverInitClass(JNIEnv * env) - { - cls = FindClass(env, PKG"RTCRtpTransceiverInit"); - - direction = GetFieldID(env, cls, "direction", "L" PKG "RTCRtpTransceiverDirection;"); - streamIds = GetFieldID(env, cls, "streamIds", LIST_SIG); - sendEncodings = GetFieldID(env, cls, "sendEncodings", LIST_SIG); - } - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/api/VideoFrame.cpp b/webrtc-jni/src/main/cpp/src/api/VideoFrame.cpp deleted file mode 100644 index 26d9b67..0000000 --- a/webrtc-jni/src/main/cpp/src/api/VideoFrame.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "api/VideoFrame.h" -#include "JavaObject.h" -#include "JavaUtils.h" -#include "JNI_WebRTC.h" - -#include "api/video/i420_buffer.h" -#include "rtc_base/time_utils.h" - -namespace jni -{ - namespace VideoFrame - { - webrtc::VideoFrame toNative(JNIEnv * env, const JavaRef & javaFrame) - { - const auto javaClass = JavaClasses::get(env); - JavaObject obj(env, javaFrame); - - int rotation = obj.getInt(javaClass->rotation); - int64_t timestamp_ns = obj.getLong(javaClass->timestampNs); - JavaLocalRef jBuffer = obj.getObject(javaClass->buffer); - - /* - // Get the I420Buffer properties - const auto i420Class = JavaClasses::get(env); - JavaObject bufferObj(env, jBuffer); - - int width = bufferObj.getInt(i420Class->width); - int height = bufferObj.getInt(i420Class->height); - - JavaLocalRef dataY = bufferObj.getObject(i420Class->dataY); - JavaLocalRef dataU = bufferObj.getObject(i420Class->dataU); - JavaLocalRef dataV = bufferObj.getObject(i420Class->dataV); - - int strideY = bufferObj.getInt(i420Class->strideY); - int strideU = bufferObj.getInt(i420Class->strideU); - int strideV = bufferObj.getInt(i420Class->strideV); - - // Get the direct buffer addresses - const uint8_t * y_data = static_cast(env->GetDirectBufferAddress(dataY.get())); - const uint8_t * u_data = static_cast(env->GetDirectBufferAddress(dataU.get())); - const uint8_t * v_data = static_cast(env->GetDirectBufferAddress(dataV.get())); - - // Create a native I420Buffer - webrtc::scoped_refptr buffer = webrtc::I420Buffer::Copy( - width, height, y_data, strideY, u_data, strideU, v_data, strideV); - */ - - webrtc::I420BufferInterface * i420Buffer = GetHandle(env, jBuffer); - webrtc::scoped_refptr buffer(i420Buffer); - - return webrtc::VideoFrame::Builder() - .set_video_frame_buffer(buffer) - //.set_timestamp_rtp(timestamp_rtp) - .set_timestamp_ms(timestamp_ns / webrtc::kNumNanosecsPerMillisec) - .set_rotation(static_cast(rotation)) - .build(); - } - } - - namespace I420Buffer - { - JavaLocalRef toJava(JNIEnv * env, const webrtc::scoped_refptr & buffer) - { - const auto javaClass = JavaClasses::get(env); - - jobject yBuffer = env->NewDirectByteBuffer(const_cast(buffer->DataY()), static_cast(buffer->StrideY()) * buffer->height()); - jobject uBuffer = env->NewDirectByteBuffer(const_cast(buffer->DataU()), static_cast(buffer->StrideU()) * buffer->ChromaHeight()); - jobject vBuffer = env->NewDirectByteBuffer(const_cast(buffer->DataV()), static_cast(buffer->StrideV()) * buffer->ChromaHeight()); - - jobject jBuffer = env->NewObject(javaClass->cls, javaClass->ctor, buffer->width(), buffer->height(), - yBuffer, buffer->StrideY(), uBuffer, buffer->StrideU(), vBuffer, buffer->StrideV()); - - SetHandle(env, jBuffer, buffer.get()); - - env->DeleteLocalRef(yBuffer); - env->DeleteLocalRef(uBuffer); - env->DeleteLocalRef(vBuffer); - - return JavaLocalRef(env, jBuffer); - } - } - - JavaVideoFrameClass::JavaVideoFrameClass(JNIEnv * env) - { - cls = FindClass(env, PKG_VIDEO"VideoFrame"); - - ctor = GetMethod(env, cls, "", "(L" PKG_VIDEO "VideoFrameBuffer;IJ)V"); - - buffer = GetFieldID(env, cls, "buffer", "L" PKG_VIDEO "VideoFrameBuffer;"); - rotation = GetFieldID(env, cls, "rotation", "I"); - timestampNs = GetFieldID(env, cls, "timestampNs", "J"); - } - - JavaNativeI420BufferClass::JavaNativeI420BufferClass(JNIEnv * env) - { - cls = FindClass(env, PKG_VIDEO"NativeI420Buffer"); - - ctor = GetMethod(env, cls, "", "(II" BYTE_BUFFER_SIG "I" BYTE_BUFFER_SIG "I" BYTE_BUFFER_SIG "I)V"); - - dataY = GetFieldID(env, cls, "dataY", BYTE_BUFFER_SIG); - dataU = GetFieldID(env, cls, "dataU", BYTE_BUFFER_SIG); - dataV = GetFieldID(env, cls, "dataV", BYTE_BUFFER_SIG); - strideY = GetFieldID(env, cls, "strideY", "I"); - strideU = GetFieldID(env, cls, "strideU", "I"); - strideV = GetFieldID(env, cls, "strideV", "I"); - width = GetFieldID(env, cls, "width", "I"); - height = GetFieldID(env, cls, "height", "I"); - } -} diff --git a/webrtc-jni/src/main/cpp/src/api/VideoTrackSink.cpp b/webrtc-jni/src/main/cpp/src/api/VideoTrackSink.cpp deleted file mode 100644 index 97d4e7e..0000000 --- a/webrtc-jni/src/main/cpp/src/api/VideoTrackSink.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "api/VideoTrackSink.h" -#include "JavaClasses.h" -#include "JNI_WebRTC.h" - -#include "api/video/i420_buffer.h" -#include "rtc_base/time_utils.h" - -namespace jni -{ - VideoTrackSink::VideoTrackSink(JNIEnv * env, const JavaGlobalRef & sink) : - sink(sink), - javaClass(JavaClasses::get(env)), - javaFrameClass(JavaClasses::get(env)), - javaBufferClass(JavaClasses::get(env)) - { - } - - void VideoTrackSink::OnFrame(const webrtc::VideoFrame & frame) - { - JNIEnv * env = AttachCurrentThread(); - - webrtc::scoped_refptr buffer = frame.video_frame_buffer(); - webrtc::scoped_refptr i420Buffer = buffer->ToI420(); - - if (i420Buffer == nullptr) { - return; - } - - webrtc::scoped_refptr i420BufferCopy = webrtc::I420Buffer::Copy(*i420Buffer); - i420BufferCopy->AddRef(); - - jint rotation = static_cast(frame.rotation()); - jlong timestamp = frame.timestamp_us() * webrtc::kNumNanosecsPerMicrosec; - - JavaLocalRef jBuffer = I420Buffer::toJava(env, i420BufferCopy); - jobject jFrame = env->NewObject(javaFrameClass->cls, javaFrameClass->ctor, jBuffer.get(), rotation, timestamp); - - env->CallVoidMethod(sink, javaClass->onFrame, jFrame); - ExceptionCheck(env); - env->DeleteLocalRef(jBuffer); - env->DeleteLocalRef(jFrame); - } - - VideoTrackSink::JavaVideoTrackSinkClass::JavaVideoTrackSinkClass(JNIEnv * env) - { - jclass cls = FindClass(env, PKG_VIDEO"VideoTrackSink"); - - onFrame = GetMethod(env, cls, "onVideoFrame", "(L" PKG_VIDEO "VideoFrame;)V"); - } -} diff --git a/webrtc-jni/src/main/cpp/src/media/Device.cpp b/webrtc-jni/src/main/cpp/src/media/Device.cpp deleted file mode 100644 index 5156bf3..0000000 --- a/webrtc-jni/src/main/cpp/src/media/Device.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/Device.h" -#include "JavaClasses.h" -#include "JavaString.h" -#include "JNI_WebRTC.h" -#include "JavaEnums.h" - -namespace jni -{ - namespace avdev - { - Device::Device(std::string name, std::string descriptor) : - name(name), - descriptor(descriptor), - deviceTransport(DeviceTransport::trUnknown), - deviceFormFactor(DeviceFormFactor::ffUnknown) - { - } - - bool Device::operator==(const Device & other) - { - return name == other.name && descriptor == other.descriptor; - } - - bool Device::operator!=(const Device & other) - { - return !(*this == other); - } - - bool Device::operator<(const Device & other) - { - return name < other.name; - } - - std::string Device::getDescriptor() const - { - return descriptor; - } - - std::string Device::getName() const - { - return name; - } - - DeviceTransport Device::getDeviceTransport() - { - return deviceTransport; - } - - DeviceFormFactor Device::getDeviceFormFactor() - { - return deviceFormFactor; - } - - void Device::setDeviceTransport(DeviceTransport newDeviceTransport) - { - deviceTransport = newDeviceTransport; - } - - void Device::setDeviceFormFactor(DeviceFormFactor newDeviceFormFactor) - { - deviceFormFactor = newDeviceFormFactor; - } - } - - namespace Device - { - JavaLocalRef toJavaDevice(JNIEnv * env, avdev::DevicePtr device) - { - const auto javaClass = JavaClasses::get(env); - - jobject obj = env->NewObject(javaClass->cls, javaClass->ctor, - JavaString::toJava(env, device->getName()).get(), - JavaString::toJava(env, device->getDescriptor()).get()); - - auto deviceTransport = JavaEnums::toJava(env, device->getDeviceTransport()); - env->SetObjectField(obj, javaClass->deviceTransport, deviceTransport.get()); - - auto deviceFormFactor = JavaEnums::toJava(env, device->getDeviceFormFactor()); - env->SetObjectField(obj, javaClass->deviceFormFactor, deviceFormFactor.get()); - - return JavaLocalRef(env, obj); - } - - JavaDeviceClass::JavaDeviceClass(JNIEnv * env) - { - cls = FindClass(env, PKG_AUDIO"Device"); - - ctor = GetMethod(env, cls, "", "(" STRING_SIG STRING_SIG ")V"); - - name = GetFieldID(env, cls, "name", STRING_SIG); - descriptor = GetFieldID(env, cls, "descriptor", STRING_SIG); - deviceTransport = GetFieldID(env, cls, "deviceTransport", "L" PKG_MEDIA "DeviceTransport;"); - deviceFormFactor = GetFieldID(env, cls, "deviceFormFactor", "L" PKG_MEDIA "DeviceFormFactor;"); - } - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/DeviceChangeListener.cpp b/webrtc-jni/src/main/cpp/src/media/DeviceChangeListener.cpp deleted file mode 100644 index ea5b851..0000000 --- a/webrtc-jni/src/main/cpp/src/media/DeviceChangeListener.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/DeviceChangeListener.h" -#include "media/audio/AudioDevice.h" -#include "media/video/VideoDevice.h" -#include "JavaFactories.h" -#include "JavaString.h" -#include "JavaUtils.h" -#include "JNI_WebRTC.h" - -namespace jni -{ - DeviceChangeListener::DeviceChangeListener(JNIEnv * env, const JavaGlobalRef & listener) : - listener(listener), - javaClass(JavaClasses::get(env)) - { - } - - void DeviceChangeListener::deviceConnected(avdev::DevicePtr device) - { - JNIEnv * env = AttachCurrentThread(); - JavaLocalRef jdevice = nullptr; - - if (dynamic_cast(device.get())) { - jdevice = AudioDevice::toJavaAudioDevice(env, device); - } - else if (dynamic_cast(device.get())) { - const auto dev = dynamic_cast(device.get()); - jdevice = VideoDevice::toJavaVideoDevice(env, *dev); - } - - if (jdevice) { - env->CallVoidMethod(listener, javaClass->deviceConnected, jdevice.get()); - } - } - - void DeviceChangeListener::deviceDisconnected(avdev::DevicePtr device) - { - JNIEnv * env = AttachCurrentThread(); - JavaLocalRef jdevice = nullptr; - - if (dynamic_cast(device.get())) { - jdevice = AudioDevice::toJavaAudioDevice(env, device); - } - else if (dynamic_cast(device.get())) { - const auto dev = dynamic_cast(device.get()); - jdevice = VideoDevice::toJavaVideoDevice(env, *dev); - } - - if (jdevice) { - env->CallVoidMethod(listener, javaClass->deviceDisconnected, jdevice.get()); - } - } - - DeviceChangeListener::JavaDeviceChangeListenerClass::JavaDeviceChangeListenerClass(JNIEnv * env) - { - jclass cls = FindClass(env, PKG_MEDIA"DeviceChangeListener"); - - deviceConnected = GetMethod(env, cls, "deviceConnected", "(L" PKG_MEDIA "Device;)V"); - deviceDisconnected = GetMethod(env, cls, "deviceDisconnected", "(L" PKG_MEDIA "Device;)V"); - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/DeviceManager.cpp b/webrtc-jni/src/main/cpp/src/media/DeviceManager.cpp deleted file mode 100644 index ed1be51..0000000 --- a/webrtc-jni/src/main/cpp/src/media/DeviceManager.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/DeviceManager.h" - -namespace jni -{ - namespace avdev - { - void DeviceManager::attachHotplugListener(PDeviceHotplugListener listener) - { - hotplugListeners.push_back(listener); - } - - void DeviceManager::detachHotplugListener(PDeviceHotplugListener listener) - { - hotplugListeners.remove_if([listener](std::weak_ptr p) { - return !(p.owner_before(listener) || listener.owner_before(p)); - }); - } - - void DeviceManager::notifyDeviceConnected(DevicePtr device) - { - notifyListeners(device, DeviceEvent::Connected); - } - - void DeviceManager::notifyDeviceDisconnected(DevicePtr device) - { - notifyListeners(device, DeviceEvent::Disconnected); - } - - void DeviceManager::notifyListeners(DevicePtr device, const DeviceEvent event) - { - for (auto i = hotplugListeners.begin(); i != hotplugListeners.end();) { - if ((*i).expired()) { - i = hotplugListeners.erase(i); - } - else { - PDeviceHotplugListener listener = (*i).lock(); - - if (event == DeviceEvent::Connected) { - listener->deviceConnected(device); - } - else if (event == DeviceEvent::Disconnected) { - listener->deviceDisconnected(device); - } - - ++i; - } - } - } - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/MediaStreamTrackObserver.cpp b/webrtc-jni/src/main/cpp/src/media/MediaStreamTrackObserver.cpp deleted file mode 100644 index 762683a..0000000 --- a/webrtc-jni/src/main/cpp/src/media/MediaStreamTrackObserver.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2022 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/MediaStreamTrackObserver.h" -#include "JavaFactories.h" -#include "JavaUtils.h" -#include "JNI_WebRTC.h" - -namespace jni -{ - MediaStreamTrackObserver::MediaStreamTrackObserver(JNIEnv * env, const JavaGlobalRef & javaTrack, const webrtc::MediaStreamTrackInterface * track, const MediaStreamTrackEvent & eventType) : - javaTrack(javaTrack), - track(track), - eventType(eventType), - javaClass(JavaClasses::get(env)) - { - trackEnabled = track->enabled(); - trackState = track->state(); - } - - void MediaStreamTrackObserver::OnChanged() - { - JNIEnv * env = AttachCurrentThread(); - - // Check state changes. - - if (eventType == MediaStreamTrackEvent::mute) { - if (track->enabled() != trackEnabled) { - // The condition "muted" is managed using the "enabled" property. - env->CallVoidMethod(javaTrack, javaClass->onTrackMute, createJavaTrack(env).release(), !track->enabled()); - ExceptionCheck(env); - } - } - else if (eventType == MediaStreamTrackEvent::ended) { - if (track->state() != trackState && track->state() == webrtc::MediaStreamTrackInterface::TrackState::kEnded) { - env->CallVoidMethod(javaTrack, javaClass->onTrackEnd, createJavaTrack(env).release()); - ExceptionCheck(env); - } - } - - // Save current state. - trackEnabled = track->enabled(); - trackState = track->state(); - } - - JavaLocalRef MediaStreamTrackObserver::createJavaTrack(JNIEnv * env) - { - if (const webrtc::AudioTrackInterface * t = dynamic_cast(track)) { - return jni::JavaFactories::create(env, t); - } - else if (const webrtc::VideoTrackInterface * t = dynamic_cast(track)) { - return jni::JavaFactories::create(env, t); - } - else { - return jni::JavaLocalRef(env, nullptr); - } - } - - MediaStreamTrackObserver::JavaMediaStreamTrackListenerClass::JavaMediaStreamTrackListenerClass(JNIEnv * env) - { - jclass clsEnded = FindClass(env, PKG_MEDIA"MediaStreamTrackEndedListener"); - jclass clsMute = FindClass(env, PKG_MEDIA"MediaStreamTrackMuteListener"); - - onTrackEnd = GetMethod(env, clsEnded, "onTrackEnd", "(L" PKG_MEDIA "MediaStreamTrack;)V"); - onTrackMute = GetMethod(env, clsMute, "onTrackMute", "(L" PKG_MEDIA "MediaStreamTrack;Z)V"); - } -} diff --git a/webrtc-jni/src/main/cpp/src/media/SyncClock.cpp b/webrtc-jni/src/main/cpp/src/media/SyncClock.cpp deleted file mode 100644 index 6f3872c..0000000 --- a/webrtc-jni/src/main/cpp/src/media/SyncClock.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/SyncClock.h" - -namespace jni -{ - SyncClock::SyncClock() : - start_time_(std::chrono::steady_clock::now()) - { - } - - int64_t SyncClock::GetTimestampUs() const - { - auto now = std::chrono::steady_clock::now(); - auto duration = now - start_time_; - return std::chrono::duration_cast(duration).count(); - } - - int64_t SyncClock::GetTimestampMs() const - { - return GetTimestampUs() / 1000; - } - - webrtc::NtpTime SyncClock::GetNtpTime() const - { - return webrtc::Clock::GetRealTimeClock()->CurrentNtpTime(); - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/audio/AudioConverter.cpp b/webrtc-jni/src/main/cpp/src/media/audio/AudioConverter.cpp deleted file mode 100644 index 7014a44..0000000 --- a/webrtc-jni/src/main/cpp/src/media/audio/AudioConverter.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/audio/AudioConverter.h" - -#include - -#include "audio/utility/channel_mixer.h" -#include "common_audio/resampler/include/push_resampler.h" - -namespace jni -{ - class CopyConverter : public AudioConverter { - public: - CopyConverter(size_t srcFrames, size_t srcChannels, size_t dstFrames, size_t dstChannels) - : AudioConverter(srcFrames, srcChannels, dstFrames, dstChannels) - { - } - - ~CopyConverter() override - { - } - - void convert(const int16_t * src, size_t srcSize, int16_t * dst, size_t dstSize) override { - checkSizes(srcSize, dstSize); - - if (src != dst) { - std::memcpy(dst, src, dstFrames * dstChannels * sizeof(int16_t)); - } - } - }; - - - class ChannelConverter : public AudioConverter { - public: - ChannelConverter(size_t srcFrames, size_t srcChannels, size_t dstFrames, size_t dstChannels) - : AudioConverter(srcFrames, srcChannels, dstFrames, dstChannels) - { - webrtc::ChannelLayout srcLayout = webrtc::GuessChannelLayout(static_cast(srcChannels)); - webrtc::ChannelLayout dstLayout = webrtc::GuessChannelLayout(static_cast(dstChannels)); - - mixer = std::make_unique(srcLayout, dstLayout); - frame = std::make_unique(); - - frame->samples_per_channel_ = srcFrames; - frame->num_channels_ = srcChannels; - } - - ~ChannelConverter() override - { - } - - void convert(const int16_t * src, size_t srcSize, int16_t * dst, size_t dstSize) override { - checkSizes(srcSize, dstSize); - - std::memcpy(frame->mutable_data(), src, srcFrames * srcChannels * sizeof(int16_t)); - - mixer->Transform(frame.get()); - - std::memcpy(dst, frame->data(), dstFrames * dstChannels * sizeof(int16_t)); - } - - private: - std::unique_ptr mixer; - std::unique_ptr frame; - }; - - - class ResampleConverter : public AudioConverter { - public: - ResampleConverter(size_t srcFrames, size_t srcChannels, size_t dstFrames, size_t dstChannels) - : AudioConverter(srcFrames, srcChannels, dstFrames, dstChannels) - { - resampler = std::make_unique>(srcFrames, dstFrames, srcChannels); - } - - ~ResampleConverter() override - { - } - - void convert(const int16_t * src, size_t srcSamplesPerChannel, int16_t * dst, size_t dstSamplesPerChannel) override { - webrtc::InterleavedView srcView(src, srcSamplesPerChannel, srcChannels); - webrtc::InterleavedView dstView(dst, dstSamplesPerChannel, srcChannels); - - resampler->Resample(srcView, dstView); - } - - private: - std::unique_ptr> resampler; - }; - - - class CompositionConverter : public AudioConverter { - public: - explicit CompositionConverter(std::vector> converters_) - : converters(std::move(converters_)) - { - RTC_CHECK_GE(converters.size(), 2); - - // We need an intermediate buffer after every converter. - for (auto it = converters.begin(); it != converters.end() - 1; ++it) { - buffers.push_back(std::vector((*it)->getDstFrames() * (*it)->getDstChannels(), 0)); - } - } - - ~CompositionConverter() override - { - } - - void convert(const int16_t * src, size_t srcSize, int16_t * dst, size_t dstSize) override { - converters.front()->convert(src, srcSize, buffers.front().data(), buffers.front().size()); - - for (size_t i = 2; i < converters.size(); ++i) { - auto & src_buffer = buffers[i - 2]; - auto & dst_buffer = buffers[i - 1]; - - converters[i]->convert(src_buffer.data(), src_buffer.size(), dst_buffer.data(), dst_buffer.size()); - } - - converters.back()->convert(buffers.back().data(), buffers.back().size(), dst, dstSize); - } - - private: - std::vector> converters; - std::vector> buffers; - }; - - - std::unique_ptr AudioConverter::create(size_t srcFrames, size_t srcChannels, size_t dstFrames, size_t dstChannels) - { - std::unique_ptr converter; - - if (srcChannels > dstChannels) { - if (srcFrames != dstFrames) { - std::vector> converters; - converters.push_back(std::unique_ptr(new ChannelConverter(srcFrames, srcChannels, srcFrames, dstChannels))); - converters.push_back(std::unique_ptr(new ResampleConverter(srcFrames, dstChannels, dstFrames, dstChannels))); - - converter.reset(new CompositionConverter(std::move(converters))); - } - else { - converter.reset(new ChannelConverter(srcFrames, srcChannels, dstFrames, dstChannels)); - } - } - else if (srcChannels < dstChannels) { - if (srcFrames != dstFrames) { - std::vector> converters; - converters.push_back(std::unique_ptr(new ResampleConverter(srcFrames, srcChannels, dstFrames, srcChannels))); - converters.push_back(std::unique_ptr(new ChannelConverter(dstFrames, srcChannels, dstFrames, dstChannels))); - - converter.reset(new CompositionConverter(std::move(converters))); - } - else { - converter.reset(new ChannelConverter(srcFrames, srcChannels, dstFrames, dstChannels)); - } - } - else if (srcFrames != dstFrames) { - converter.reset(new ResampleConverter(srcFrames, srcChannels, dstFrames, dstChannels)); - } - else { - converter.reset(new CopyConverter(srcFrames, srcChannels, dstFrames, dstChannels)); - } - - return converter; - } - - AudioConverter::AudioConverter() : - srcFrames(0), - srcChannels(0), - dstFrames(0), - dstChannels(0) - { - } - - AudioConverter::AudioConverter(size_t srcFrames, size_t srcChannels, size_t dstFrames, size_t dstChannels) : - srcFrames(srcFrames), - srcChannels(srcChannels), - dstFrames(dstFrames), - dstChannels(dstChannels) - { - } - - void AudioConverter::checkSizes(size_t srcSize, size_t dstCapacity) const { - RTC_CHECK_EQ(srcSize, srcChannels * srcFrames); - RTC_CHECK_GE(dstCapacity, dstChannels * dstFrames); - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/audio/AudioDevice.cpp b/webrtc-jni/src/main/cpp/src/media/audio/AudioDevice.cpp deleted file mode 100644 index 0737d8b..0000000 --- a/webrtc-jni/src/main/cpp/src/media/audio/AudioDevice.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/audio/AudioDevice.h" - -#include "JavaClasses.h" -#include "JavaString.h" -#include "JNI_WebRTC.h" -#include "JavaEnums.h" - -namespace jni -{ - namespace avdev - { - AudioDevice::AudioDevice(std::string name, std::string descriptor) : - Device(name, descriptor), - directionType(AudioDeviceDirectionType::adtUnknown) - { - } - } - - namespace AudioDevice - { - JavaLocalRef toJavaAudioDevice(JNIEnv * env, avdev::DevicePtr device) - { - const auto javaClass = JavaClasses::get(env); - - jobject obj = env->NewObject(javaClass->cls, javaClass->ctor, - JavaString::toJava(env, device->getName()).get(), - JavaString::toJava(env, device->getDescriptor()).get()); - - auto deviceTransport = JavaEnums::toJava(env, device->getDeviceTransport()); - env->SetObjectField(obj, javaClass->deviceTransport, deviceTransport.get()); - - auto deviceFormFactor = JavaEnums::toJava(env, device->getDeviceFormFactor()); - env->SetObjectField(obj, javaClass->deviceFormFactor, deviceFormFactor.get()); - - auto audioDevice = dynamic_cast(device.get()); - auto directionType = JavaEnums::toJava(env, audioDevice->directionType); - env->SetObjectField(obj, javaClass->directionType, directionType.get()); - - return JavaLocalRef(env, obj); - } - - JavaAudioDeviceClass::JavaAudioDeviceClass(JNIEnv * env) - { - cls = FindClass(env, PKG_AUDIO"AudioDevice"); - - ctor = GetMethod(env, cls, "", "(" STRING_SIG STRING_SIG ")V"); - - name = GetFieldID(env, cls, "name", STRING_SIG); - descriptor = GetFieldID(env, cls, "descriptor", STRING_SIG); - directionType = GetFieldID(env, cls, "directionType", "L" PKG_MEDIA "AudioDeviceDirectionType;"); - deviceTransport = GetFieldID(env, cls, "deviceTransport", "L" PKG_MEDIA "DeviceTransport;"); - deviceFormFactor = GetFieldID(env, cls, "deviceFormFactor", "L" PKG_MEDIA "DeviceFormFactor;"); - } - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/audio/AudioDeviceManager.cpp b/webrtc-jni/src/main/cpp/src/media/audio/AudioDeviceManager.cpp deleted file mode 100644 index f43eed4..0000000 --- a/webrtc-jni/src/main/cpp/src/media/audio/AudioDeviceManager.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/audio/AudioDeviceManager.h" - -namespace jni -{ - namespace avdev - { - AudioDeviceManager::AudioDeviceManager() - { - } - - AudioDevicePtr AudioDeviceManager::getDefaultAudioCaptureDevice() - { - if (getDefaultCaptureDevice() == nullptr && captureDevices.empty()) { - getAudioCaptureDevices(); - } - - if (getDefaultCaptureDevice() == nullptr && !captureDevices.empty()) { - setDefaultCaptureDevice(*captureDevices.devices().begin()); - } - - return getDefaultCaptureDevice(); - } - - AudioDevicePtr AudioDeviceManager::getDefaultAudioPlaybackDevice() - { - if (getDefaultPlaybackDevice() == nullptr && playbackDevices.empty()) { - getAudioPlaybackDevices(); - } - - if (getDefaultPlaybackDevice() == nullptr && !playbackDevices.empty()) { - setDefaultPlaybackDevice(*playbackDevices.devices().begin()); - } - - return getDefaultPlaybackDevice(); - } - - void AudioDeviceManager::setDefaultCaptureDevice(AudioDevicePtr device) - { - std::unique_lock mlock(mutex); - - defaultCaptureDevice = device; - } - - - AudioDevicePtr AudioDeviceManager::getDefaultCaptureDevice() - { - std::unique_lock mlock(mutex); - - return defaultCaptureDevice; - } - - void AudioDeviceManager::setDefaultPlaybackDevice(AudioDevicePtr device) - { - std::unique_lock mlock(mutex); - - defaultPlaybackDevice = device; - } - - AudioDevicePtr AudioDeviceManager::getDefaultPlaybackDevice() - { - std::unique_lock mlock(mutex); - - return defaultPlaybackDevice; - } - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/audio/AudioProcessing.cpp b/webrtc-jni/src/main/cpp/src/media/audio/AudioProcessing.cpp deleted file mode 100644 index 9fc0609..0000000 --- a/webrtc-jni/src/main/cpp/src/media/audio/AudioProcessing.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/audio/AudioProcessing.h" -#include "media/audio/AudioProcessingStats.h" - -#include "JavaClasses.h" -#include "JavaObject.h" -#include "JavaUtils.h" -#include "JNI_WebRTC.h" - -namespace jni -{ - namespace AudioProcessing - { - void updateStats(const webrtc::AudioProcessingStats & stats, JNIEnv * env, const JavaRef & javaType) - { - const auto javaClass = JavaClasses::get(env); - const auto javaStatsClass = JavaClasses::get(env); - - JavaObject obj(env, javaType); - JavaObject statsObj(env, obj.getObject(javaClass->stats)); - - statsObj.setDouble(javaStatsClass->echoReturnLoss, stats.echo_return_loss.value_or(0)); - statsObj.setDouble(javaStatsClass->echoReturnLossEnhancement, stats.echo_return_loss_enhancement.value_or(0)); - statsObj.setDouble(javaStatsClass->divergentFilterFraction, stats.divergent_filter_fraction.value_or(0)); - statsObj.setInt(javaStatsClass->delayMs, stats.delay_ms.value_or(0)); - statsObj.setInt(javaStatsClass->delayMedianMs, stats.delay_median_ms.value_or(0)); - statsObj.setInt(javaStatsClass->delayStandardDeviationMs, stats.delay_standard_deviation_ms.value_or(0)); - statsObj.setDouble(javaStatsClass->residualEchoLikelihood, stats.residual_echo_likelihood.value_or(0)); - statsObj.setDouble(javaStatsClass->residualEchoLikelihoodRecentMax, stats.residual_echo_likelihood_recent_max.value_or(0)); - } - - JavaAudioProcessingClass::JavaAudioProcessingClass(JNIEnv * env) - { - cls = FindClass(env, PKG_AUDIO"AudioProcessing"); - - stats = GetFieldID(env, cls, "stats", "L" PKG_AUDIO "AudioProcessingStats;"); - } - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/audio/AudioProcessingConfig.cpp b/webrtc-jni/src/main/cpp/src/media/audio/AudioProcessingConfig.cpp deleted file mode 100644 index a27f095..0000000 --- a/webrtc-jni/src/main/cpp/src/media/audio/AudioProcessingConfig.cpp +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/audio/AudioProcessingConfig.h" - -#include "JavaClasses.h" -#include "JavaEnums.h" -#include "JavaObject.h" -#include "JavaRef.h" -#include "JavaUtils.h" -#include "JNI_WebRTC.h" - -namespace jni -{ - namespace AudioProcessingConfig - { - webrtc::AudioProcessing::Config toNative(JNIEnv * env, const JavaRef & javaType) - { - const auto javaClass = JavaClasses::get(env); - const auto javaEchoCancellerClass = JavaClasses::get(env); - const auto javaHighPassFilterClass = JavaClasses::get(env); - const auto javaNoiseSuppressionClass = JavaClasses::get(env); - const auto javaCaptureLevelAdjustmentClass = JavaClasses::get(env); - const auto javaAnalogMicGainEmulationClass = JavaClasses::get(env); - - JavaObject obj(env, javaType); - JavaObject echoCanceller(env, obj.getObject(javaClass->echoCanceller)); - JavaObject highPassFilter(env, obj.getObject(javaClass->highPassFilter)); - JavaObject noiseSuppression(env, obj.getObject(javaClass->noiseSuppression)); - JavaObject captureLevelAdjustment(env, obj.getObject(javaClass->captureLevelAdjustment)); - JavaObject analogMicGainEmulation(env, captureLevelAdjustment.getObject(javaCaptureLevelAdjustmentClass->analogMicGainEmulation)); - - webrtc::AudioProcessing::Config config; - - config.pipeline = toPipeline(env, obj.getObject(javaClass->pipeline)); - config.echo_canceller.enabled = echoCanceller.getBoolean(javaEchoCancellerClass->enabled); - config.high_pass_filter.enabled = highPassFilter.getBoolean(javaHighPassFilterClass->enabled); - config.noise_suppression.enabled = noiseSuppression.getBoolean(javaNoiseSuppressionClass->enabled); - config.echo_canceller.enforce_high_pass_filtering = echoCanceller.getBoolean(javaEchoCancellerClass->enforceHighPassFiltering); - config.capture_level_adjustment.enabled = captureLevelAdjustment.getBoolean(javaCaptureLevelAdjustmentClass->enabled); - config.capture_level_adjustment.pre_gain_factor = captureLevelAdjustment.getFloat(javaCaptureLevelAdjustmentClass->preGainFactor); - config.capture_level_adjustment.post_gain_factor = captureLevelAdjustment.getFloat(javaCaptureLevelAdjustmentClass->postGainFactor); - config.capture_level_adjustment.analog_mic_gain_emulation.enabled = analogMicGainEmulation.getBoolean(javaAnalogMicGainEmulationClass->enabled); - config.capture_level_adjustment.analog_mic_gain_emulation.initial_level = analogMicGainEmulation.getInt(javaAnalogMicGainEmulationClass->initialLevel); - config.gain_controller1 = toGainController1(env, obj.getObject(javaClass->gainController)); - config.gain_controller2 = toGainController2(env, obj.getObject(javaClass->gainControllerDigital)); - - JavaLocalRef nsLevel = noiseSuppression.getObject(javaNoiseSuppressionClass->level); - - if (nsLevel.get()) { - config.noise_suppression.level = jni::JavaEnums::toNative(env, nsLevel); - } - - return config; - } - - webrtc::AudioProcessing::Config::Pipeline toPipeline(JNIEnv * env, const JavaLocalRef & javaType) - { - const auto javaPipelineClass = JavaClasses::get(env); - - JavaObject jPipeline(env, javaType); - - JavaLocalRef downmixMethod = jPipeline.getObject(javaPipelineClass->captureDownmixMethod); - - webrtc::AudioProcessing::Config::Pipeline pipeline; - - pipeline.maximum_internal_processing_rate = jPipeline.getInt(javaPipelineClass->maximumInternalProcessingRate); - pipeline.multi_channel_render = jPipeline.getBoolean(javaPipelineClass->multiChannelRender); - pipeline.multi_channel_capture = jPipeline.getBoolean(javaPipelineClass->multiChannelCapture); - pipeline.capture_downmix_method = JavaEnums::toNative(env, downmixMethod); - - return pipeline; - } - - webrtc::AudioProcessing::Config::GainController2 toGainController2(JNIEnv * env, const JavaLocalRef & javaType) - { - const auto javaGainControlClass = JavaClasses::get(env); - const auto javaInputVolumeControllerClass = JavaClasses::get(env); - const auto javaGainControlFixedDigitalClass = JavaClasses::get(env); - const auto javaGainControlAdaptiveDigitalClass = JavaClasses::get(env); - - JavaObject gainControl(env, javaType); - JavaObject inputVolumeController(env, gainControl.getObject(javaGainControlClass->inputVolumeController)); - JavaObject gainControlFixedDigital(env, gainControl.getObject(javaGainControlClass->fixedDigital)); - JavaObject gainControlAdaptiveDigital(env, gainControl.getObject(javaGainControlClass->adaptiveDigital)); - - webrtc::AudioProcessing::Config::GainController2 gainController; - - gainController.enabled = gainControl.getBoolean(javaGainControlClass->enabled); - gainController.input_volume_controller.enabled = inputVolumeController.getBoolean(javaInputVolumeControllerClass->enabled); - gainController.fixed_digital.gain_db = gainControlFixedDigital.getFloat(javaGainControlFixedDigitalClass->gainDb); - gainController.adaptive_digital.enabled = gainControlAdaptiveDigital.getBoolean(javaGainControlAdaptiveDigitalClass->enabled); - gainController.adaptive_digital.headroom_db = gainControlAdaptiveDigital.getFloat(javaGainControlAdaptiveDigitalClass->headroomDb); - gainController.adaptive_digital.initial_gain_db = gainControlAdaptiveDigital.getFloat(javaGainControlAdaptiveDigitalClass->initialGainDb); - gainController.adaptive_digital.max_gain_db = gainControlAdaptiveDigital.getFloat(javaGainControlAdaptiveDigitalClass->maxGainDb); - gainController.adaptive_digital.max_gain_change_db_per_second = gainControlAdaptiveDigital.getFloat(javaGainControlAdaptiveDigitalClass->maxGainChangeDbPerSecond); - gainController.adaptive_digital.max_output_noise_level_dbfs = gainControlAdaptiveDigital.getFloat(javaGainControlAdaptiveDigitalClass->maxOutputNoiseLevelDbfs); - - return gainController; - } - - webrtc::AudioProcessing::Config::GainController1 toGainController1(JNIEnv * env, const JavaLocalRef & javaType) - { - const auto javaGainControllerClass = JavaClasses::get(env); - const auto javaAgc1AnalogClass = JavaClasses::get(env); - const auto javaAgc1ClipPredClass = JavaClasses::get(env); - - JavaObject jGc1(env, javaType); - webrtc::AudioProcessing::Config::GainController1 gc1; - - gc1.enabled = jGc1.getBoolean(javaGainControllerClass->enabled); - gc1.target_level_dbfs = jGc1.getInt(javaGainControllerClass->targetLevelDbfs); - gc1.compression_gain_db = jGc1.getInt(javaGainControllerClass->compressionGainDb); - gc1.enable_limiter = jGc1.getBoolean(javaGainControllerClass->enableLimiter); - - JavaLocalRef mode = jGc1.getObject(javaGainControllerClass->mode); - if (mode.get()) { - gc1.mode = JavaEnums::toNative(env, mode); - } - - JavaObject jAgc(env, jGc1.getObject(javaGainControllerClass->analogGainController)); - - gc1.analog_gain_controller.enabled = jAgc.getBoolean(javaAgc1AnalogClass->enabled); - gc1.analog_gain_controller.startup_min_volume = jAgc.getInt(javaAgc1AnalogClass->startupMinVolume); - gc1.analog_gain_controller.clipped_level_min = jAgc.getInt(javaAgc1AnalogClass->clippedLevelMin); - gc1.analog_gain_controller.enable_digital_adaptive = jAgc.getBoolean(javaAgc1AnalogClass->enableDigitalAdaptive); - gc1.analog_gain_controller.clipped_level_step = jAgc.getInt(javaAgc1AnalogClass->clippedLevelStep); - gc1.analog_gain_controller.clipped_ratio_threshold = jAgc.getFloat(javaAgc1AnalogClass->clippedRatioThreshold); - gc1.analog_gain_controller.clipped_wait_frames = jAgc.getInt(javaAgc1AnalogClass->clippedWaitFrames); - - JavaObject jPred(env, jAgc.getObject(javaAgc1AnalogClass->clippingPredictor)); - - gc1.analog_gain_controller.clipping_predictor.enabled = jPred.getBoolean(javaAgc1ClipPredClass->enabled); - JavaLocalRef predMode = jPred.getObject(javaAgc1ClipPredClass->mode); - - if (predMode.get()) { - gc1.analog_gain_controller.clipping_predictor.mode = JavaEnums::toNative(env, predMode); - } - - gc1.analog_gain_controller.clipping_predictor.window_length = jPred.getInt(javaAgc1ClipPredClass->windowLength); - gc1.analog_gain_controller.clipping_predictor.reference_window_length = jPred.getInt(javaAgc1ClipPredClass->referenceWindowLength); - gc1.analog_gain_controller.clipping_predictor.reference_window_delay = jPred.getInt(javaAgc1ClipPredClass->referenceWindowDelay); - gc1.analog_gain_controller.clipping_predictor.clipping_threshold = jPred.getFloat(javaAgc1ClipPredClass->clippingThreshold); - gc1.analog_gain_controller.clipping_predictor.crest_factor_margin = jPred.getFloat(javaAgc1ClipPredClass->crestFactorMargin); - gc1.analog_gain_controller.clipping_predictor.use_predicted_step = jPred.getBoolean(javaAgc1ClipPredClass->usePredictedStep); - - return gc1; - } - - JavaAudioProcessingConfigClass::JavaAudioProcessingConfigClass(JNIEnv * env) - { - cls = FindClass(env, PKG_AUDIO"AudioProcessingConfig"); - - pipeline = GetFieldID(env, cls, "pipeline", "L" PKG_AUDIO "AudioProcessingConfig$Pipeline;"); - echoCanceller = GetFieldID(env, cls, "echoCanceller", "L" PKG_AUDIO "AudioProcessingConfig$EchoCanceller;"); - gainControllerDigital = GetFieldID(env, cls, "gainControllerDigital", "L" PKG_AUDIO "AudioProcessingConfig$GainControllerDigital;"); - gainController = GetFieldID(env, cls, "gainController", "L" PKG_AUDIO "AudioProcessingConfig$GainController;"); - highPassFilter = GetFieldID(env, cls, "highPassFilter", "L" PKG_AUDIO "AudioProcessingConfig$HighPassFilter;"); - noiseSuppression = GetFieldID(env, cls, "noiseSuppression", "L" PKG_AUDIO "AudioProcessingConfig$NoiseSuppression;"); - captureLevelAdjustment = GetFieldID(env, cls, "captureLevelAdjustment", "L" PKG_AUDIO "AudioProcessingConfig$CaptureLevelAdjustment;"); - } - - JavaPipelineClass::JavaPipelineClass(JNIEnv* env) - { - cls = FindClass(env, PKG_AUDIO"AudioProcessingConfig$Pipeline"); - - maximumInternalProcessingRate = GetFieldID(env, cls, "maximumInternalProcessingRate", "I"); - multiChannelRender = GetFieldID(env, cls, "multiChannelRender", "Z"); - multiChannelCapture = GetFieldID(env, cls, "multiChannelCapture", "Z"); - captureDownmixMethod = GetFieldID(env, cls, "captureDownmixMethod", "L" PKG_AUDIO "AudioProcessingConfig$Pipeline$DownmixMethod;"); - } - - JavaEchoCancellerClass::JavaEchoCancellerClass(JNIEnv* env) - { - cls = FindClass(env, PKG_AUDIO"AudioProcessingConfig$EchoCanceller"); - - enabled = GetFieldID(env, cls, "enabled", "Z"); - enforceHighPassFiltering = GetFieldID(env, cls, "enforceHighPassFiltering", "Z"); - } - - JavaGainControllerDigitalClass::JavaGainControllerDigitalClass(JNIEnv* env) - { - cls = FindClass(env, PKG_AUDIO"AudioProcessingConfig$GainControllerDigital"); - - enabled = GetFieldID(env, cls, "enabled", "Z"); - inputVolumeController = GetFieldID(env, cls, "inputVolumeController", "L" PKG_AUDIO "AudioProcessingConfig$GainControllerDigital$InputVolumeController;"); - fixedDigital = GetFieldID(env, cls, "fixedDigital", "L" PKG_AUDIO "AudioProcessingConfig$GainControllerDigital$FixedDigital;"); - adaptiveDigital = GetFieldID(env, cls, "adaptiveDigital", "L" PKG_AUDIO "AudioProcessingConfig$GainControllerDigital$AdaptiveDigital;"); - } - - JavaGainControlFixedDigitalClass::JavaGainControlFixedDigitalClass(JNIEnv* env) - { - cls = FindClass(env, PKG_AUDIO"AudioProcessingConfig$GainControllerDigital$FixedDigital"); - - gainDb = GetFieldID(env, cls, "gainDb", "F"); - } - - JavaGainControlAdaptiveDigitalClass::JavaGainControlAdaptiveDigitalClass(JNIEnv* env) - { - cls = FindClass(env, PKG_AUDIO"AudioProcessingConfig$GainControllerDigital$AdaptiveDigital"); - - enabled = GetFieldID(env, cls, "enabled", "Z"); - headroomDb = GetFieldID(env, cls, "headroomDb", "F"); - maxGainDb = GetFieldID(env, cls, "maxGainDb", "F"); - initialGainDb = GetFieldID(env, cls, "initialGainDb", "F"); - maxGainChangeDbPerSecond = GetFieldID(env, cls, "maxGainChangeDbPerSecond", "F"); - maxOutputNoiseLevelDbfs = GetFieldID(env, cls, "maxOutputNoiseLevelDbfs", "F"); - } - - JavaHighPassFilterClass::JavaHighPassFilterClass(JNIEnv* env) - { - cls = FindClass(env, PKG_AUDIO"AudioProcessingConfig$HighPassFilter"); - - enabled = GetFieldID(env, cls, "enabled", "Z"); - } - - JavaGainControllerClass::JavaGainControllerClass(JNIEnv* env) - { - cls = FindClass(env, PKG_AUDIO"AudioProcessingConfig$GainController"); - - enabled = GetFieldID(env, cls, "enabled", "Z"); - targetLevelDbfs = GetFieldID(env, cls, "targetLevelDbfs", "I"); - compressionGainDb = GetFieldID(env, cls, "compressionGainDb", "I"); - enableLimiter = GetFieldID(env, cls, "enableLimiter", "Z"); - mode = GetFieldID(env, cls, "mode", "L" PKG_AUDIO "AudioProcessingConfig$GainController$Mode;"); - analogGainController = GetFieldID(env, cls, "analogGainController", "L" PKG_AUDIO "AudioProcessingConfig$GainController$AnalogGainController;"); - } - - JavaAgc1AnalogGainControllerClass::JavaAgc1AnalogGainControllerClass(JNIEnv* env) - { - cls = FindClass(env, PKG_AUDIO"AudioProcessingConfig$GainController$AnalogGainController"); - - enabled = GetFieldID(env, cls, "enabled", "Z"); - startupMinVolume = GetFieldID(env, cls, "startupMinVolume", "I"); - clippedLevelMin = GetFieldID(env, cls, "clippedLevelMin", "I"); - enableDigitalAdaptive = GetFieldID(env, cls, "enableDigitalAdaptive", "Z"); - clippedLevelStep = GetFieldID(env, cls, "clippedLevelStep", "I"); - clippedRatioThreshold = GetFieldID(env, cls, "clippedRatioThreshold", "F"); - clippedWaitFrames = GetFieldID(env, cls, "clippedWaitFrames", "I"); - clippingPredictor = GetFieldID(env, cls, "clippingPredictor", "L" PKG_AUDIO "AudioProcessingConfig$GainController$AnalogGainController$ClippingPredictor;"); - } - - JavaAgc1ClippingPredictorClass::JavaAgc1ClippingPredictorClass(JNIEnv* env) - { - cls = FindClass(env, PKG_AUDIO"AudioProcessingConfig$GainController$AnalogGainController$ClippingPredictor"); - - enabled = GetFieldID(env, cls, "enabled", "Z"); - mode = GetFieldID(env, cls, "mode", "L" PKG_AUDIO "AudioProcessingConfig$GainController$AnalogGainController$ClippingPredictor$Mode;"); - windowLength = GetFieldID(env, cls, "windowLength", "I"); - referenceWindowLength = GetFieldID(env, cls, "referenceWindowLength", "I"); - referenceWindowDelay = GetFieldID(env, cls, "referenceWindowDelay", "I"); - clippingThreshold = GetFieldID(env, cls, "clippingThreshold", "F"); - crestFactorMargin = GetFieldID(env, cls, "crestFactorMargin", "F"); - usePredictedStep = GetFieldID(env, cls, "usePredictedStep", "Z"); - } - - JavaNoiseSuppressionClass::JavaNoiseSuppressionClass(JNIEnv* env) - { - cls = FindClass(env, PKG_AUDIO"AudioProcessingConfig$NoiseSuppression"); - - enabled = GetFieldID(env, cls, "enabled", "Z"); - level = GetFieldID(env, cls, "level", "L" PKG_AUDIO "AudioProcessingConfig$NoiseSuppression$Level;"); - } - - JavaCaptureLevelAdjustmentClass::JavaCaptureLevelAdjustmentClass(JNIEnv* env) - { - cls = FindClass(env, PKG_AUDIO"AudioProcessingConfig$CaptureLevelAdjustment"); - - enabled = GetFieldID(env, cls, "enabled", "Z"); - preGainFactor = GetFieldID(env, cls, "preGainFactor", "F"); - postGainFactor = GetFieldID(env, cls, "postGainFactor", "F"); - analogMicGainEmulation = GetFieldID(env, cls, "analogMicGainEmulation", "L" PKG_AUDIO "AudioProcessingConfig$CaptureLevelAdjustment$AnalogMicGainEmulation;"); - } - - JavaAnalogMicGainEmulationClass::JavaAnalogMicGainEmulationClass(JNIEnv* env) - { - cls = FindClass(env, PKG_AUDIO"AudioProcessingConfig$CaptureLevelAdjustment$AnalogMicGainEmulation"); - - enabled = GetFieldID(env, cls, "enabled", "Z"); - initialLevel = GetFieldID(env, cls, "initialLevel", "I"); - } - - JavaInputVolumeControllerClass::JavaInputVolumeControllerClass(JNIEnv* env) - { - cls = FindClass(env, PKG_AUDIO"AudioProcessingConfig$GainControllerDigital$InputVolumeController"); - - enabled = GetFieldID(env, cls, "enabled", "Z"); - } - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/audio/AudioProcessingStats.cpp b/webrtc-jni/src/main/cpp/src/media/audio/AudioProcessingStats.cpp deleted file mode 100644 index ca1d1d9..0000000 --- a/webrtc-jni/src/main/cpp/src/media/audio/AudioProcessingStats.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/audio/AudioProcessingStats.h" - -#include "JavaClasses.h" -#include "JavaObject.h" -#include "JavaUtils.h" -#include "JNI_WebRTC.h" - -namespace jni -{ - namespace AudioProcessingStats - { - JavaAudioProcessingStatsClass::JavaAudioProcessingStatsClass(JNIEnv * env) - { - cls = FindClass(env, PKG_AUDIO"AudioProcessingStats"); - - echoReturnLoss = GetFieldID(env, cls, "echoReturnLoss", "D"); - echoReturnLossEnhancement = GetFieldID(env, cls, "echoReturnLossEnhancement", "D"); - divergentFilterFraction = GetFieldID(env, cls, "divergentFilterFraction", "D"); - delayMs = GetFieldID(env, cls, "delayMs", "I"); - delayMedianMs = GetFieldID(env, cls, "delayMedianMs", "I"); - delayStandardDeviationMs = GetFieldID(env, cls, "delayStandardDeviationMs", "I"); - residualEchoLikelihood = GetFieldID(env, cls, "residualEchoLikelihood", "D"); - residualEchoLikelihoodRecentMax = GetFieldID(env, cls, "residualEchoLikelihoodRecentMax", "D"); - } - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/audio/AudioProcessingStreamConfig.cpp b/webrtc-jni/src/main/cpp/src/media/audio/AudioProcessingStreamConfig.cpp deleted file mode 100644 index c4488cc..0000000 --- a/webrtc-jni/src/main/cpp/src/media/audio/AudioProcessingStreamConfig.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/audio/AudioProcessingStreamConfig.h" - -#include "JavaClasses.h" -#include "JavaObject.h" -#include "JavaUtils.h" -#include "JNI_WebRTC.h" - -namespace jni -{ - namespace AudioProcessingStreamConfig - { - webrtc::StreamConfig toNative(JNIEnv * env, const JavaRef & javaType) - { - const auto javaClass = JavaClasses::get(env); - - JavaObject obj(env, javaType); - - return webrtc::StreamConfig(obj.getInt(javaClass->sampleRate), obj.getInt(javaClass->channels)); - } - - JavaAudioProcessingStreamConfigClass::JavaAudioProcessingStreamConfigClass(JNIEnv * env) - { - cls = FindClass(env, PKG_AUDIO"AudioProcessingStreamConfig"); - - ctor = GetMethod(env, cls, "", "(II)V"); - - sampleRate = GetFieldID(env, cls, "sampleRate", "I"); - channels = GetFieldID(env, cls, "channels", "I"); - } - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/audio/AudioTransportSink.cpp b/webrtc-jni/src/main/cpp/src/media/audio/AudioTransportSink.cpp deleted file mode 100644 index 1a51769..0000000 --- a/webrtc-jni/src/main/cpp/src/media/audio/AudioTransportSink.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/audio/AudioTransportSink.h" -#include "JavaClasses.h" -#include "JNI_WebRTC.h" - -namespace jni -{ - AudioTransportSink::AudioTransportSink(JNIEnv * env, const JavaGlobalRef & sink) : - sink(sink), - javaClass(JavaClasses::get(env)) - { - } - - int32_t AudioTransportSink::RecordedDataIsAvailable(const void * audioSamples, - const size_t nSamples, - const size_t nBytesPerSample, - const size_t nChannels, - const uint32_t samplesPerSec, - const uint32_t totalDelayMS, - const int32_t clockDrift, - const uint32_t currentMicLevel, - const bool keyPressed, - uint32_t & newMicLevel) - { - JNIEnv * env = AttachCurrentThread(); - - const jbyte * buffer = static_cast(audioSamples); - jsize dataSize = static_cast(nSamples * nBytesPerSample); - - jbyteArray dataArray = env->NewByteArray(dataSize); - env->SetByteArrayRegion(dataArray, 0, dataSize, buffer); - env->CallVoidMethod(sink, javaClass->onRecordedData, dataArray, nSamples, nBytesPerSample, nChannels, samplesPerSec, totalDelayMS, clockDrift); - - ExceptionCheck(env); - env->DeleteLocalRef(dataArray); - - return 0; - } - - AudioTransportSink::JavaAudioSinkClass::JavaAudioSinkClass(JNIEnv * env) - { - jclass cls = FindClass(env, PKG_AUDIO"AudioSink"); - - onRecordedData = GetMethod(env, cls, "onRecordedData", "([BIIIIII)V"); - } -} diff --git a/webrtc-jni/src/main/cpp/src/media/audio/AudioTransportSource.cpp b/webrtc-jni/src/main/cpp/src/media/audio/AudioTransportSource.cpp deleted file mode 100644 index 3b1672d..0000000 --- a/webrtc-jni/src/main/cpp/src/media/audio/AudioTransportSource.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/audio/AudioTransportSource.h" -#include "JavaClasses.h" -#include "JNI_WebRTC.h" - -#include - -namespace jni -{ - AudioTransportSource::AudioTransportSource(JNIEnv * env, const JavaGlobalRef & source) : - source(source), - buffer(nullptr), - javaClass(JavaClasses::get(env)) - { - } - - int32_t AudioTransportSource::NeedMorePlayData(const size_t nSamples, - const size_t nBytesPerSample, - const size_t nChannels, - const uint32_t samplesPerSec, - void * audioSamples, - size_t & nSamplesOut, - int64_t * elapsed_time_ms, - int64_t * ntp_time_ms) - { - JNIEnv * env = AttachCurrentThread(); - - *elapsed_time_ms = 0; - *ntp_time_ms = 0; - - jsize bufferSize = static_cast(nSamples * nBytesPerSample); - - if (buffer.get() == nullptr) { - jbyteArray dataArray = env->NewByteArray(bufferSize); - - buffer = JavaGlobalRef(env, dataArray); - - jsize bufferLength = env->GetArrayLength(buffer); - - if (bufferLength < bufferSize) { - buffer = JavaGlobalRef(env, nullptr); - return 0; - } - } - - nSamplesOut = env->CallIntMethod(source, javaClass->onPlaybackData, buffer.get(), nSamples, nBytesPerSample, nChannels, samplesPerSec); - - if (nSamplesOut > 0) { - env->GetByteArrayRegion(buffer, 0, bufferSize, reinterpret_cast(audioSamples)); - } - - return 0; - } - - AudioTransportSource::JavaAudioSourceClass::JavaAudioSourceClass(JNIEnv * env) - { - jclass cls = FindClass(env, PKG_AUDIO"AudioSource"); - - onPlaybackData = GetMethod(env, cls, "onPlaybackData", "([BIIII)I"); - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/audio/CustomAudioSource.cpp b/webrtc-jni/src/main/cpp/src/media/audio/CustomAudioSource.cpp deleted file mode 100644 index 0b90cbd..0000000 --- a/webrtc-jni/src/main/cpp/src/media/audio/CustomAudioSource.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "media/audio/CustomAudioSource.h" - -#include -#include - -namespace jni -{ - CustomAudioSource::CustomAudioSource(std::shared_ptr clock) : - clock_(clock), - total_samples_captured_(0), - audio_capture_delay_us_(0) - { - } - - void CustomAudioSource::RegisterObserver(webrtc::ObserverInterface * observer) - { - // Not implemented - not needed for custom sources - } - - void CustomAudioSource::UnregisterObserver(webrtc::ObserverInterface * observer) - { - // Not implemented - not needed for custom sources - } - - void CustomAudioSource::AddSink(webrtc::AudioTrackSinkInterface * sink) - { - //webrtc::CritScope lock(&crit_); - - sinks_.push_back(sink); - } - - void CustomAudioSource::RemoveSink(webrtc::AudioTrackSinkInterface * sink) - { - //webrtc::CritScope lock(&crit_); - - sinks_.erase(std::remove(sinks_.begin(), sinks_.end(), sink), sinks_.end()); - } - - webrtc::AudioSourceInterface::SourceState CustomAudioSource::state() const - { - return kLive; - } - - bool CustomAudioSource::remote() const - { - return false; - } - - void CustomAudioSource::PushAudioData(const void * audio_data, int bits_per_sample, - int sample_rate, size_t number_of_channels, - size_t number_of_frames) - { - //webrtc::CritScope lock(&crit_); - - // Calculate absolute capture time - int64_t timestamp_us = clock_->GetTimestampUs(); - - // Apply delay if audio capture has inherent latency - timestamp_us -= audio_capture_delay_us_; - - // Calculate NTP time for this audio frame - int64_t ntp_time_ms = clock_->GetNtpTime().ToMs(); - - // Create absolute capture time - absl::optional absolute_capture_time_ms = timestamp_us / 1000; - - // Send to all sinks with timing information - for (auto * sink : sinks_) { - sink->OnData(audio_data, bits_per_sample, sample_rate, - number_of_channels, number_of_frames, - absolute_capture_time_ms); - } - - // Update total samples for tracking - total_samples_captured_ += number_of_frames; - } - - void CustomAudioSource::SetAudioCaptureDelay(int64_t delay_us) - { - audio_capture_delay_us_ = delay_us; - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/audio/RawAudioFileSink.cpp b/webrtc-jni/src/main/cpp/src/media/audio/RawAudioFileSink.cpp deleted file mode 100644 index c420aa0..0000000 --- a/webrtc-jni/src/main/cpp/src/media/audio/RawAudioFileSink.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/audio/RawAudioFileSink.h" - -#include - -namespace jni -{ - RawAudioFileSink::RawAudioFileSink(std::string fileName) - { - outputStream.open(fileName, std::ofstream::out | std::ofstream::binary | std::ofstream::trunc); - } - - RawAudioFileSink::~RawAudioFileSink() - { - outputStream.flush(); - outputStream.close(); - } - - int32_t RawAudioFileSink::RecordedDataIsAvailable( - const void * audioSamples, - const size_t nSamples, - const size_t nBytesPerSample, - const size_t nChannels, - const uint32_t samplesPerSec, - const uint32_t totalDelayMS, - const int32_t clockDrift, - const uint32_t currentMicLevel, - const bool keyPressed, - uint32_t & newMicLevel) - { - size_t audioSamplesSize = nSamples * nBytesPerSample; - - outputStream.write(static_cast(audioSamples), audioSamplesSize); - - return 0; - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/audio/RawAudioFileSource.cpp b/webrtc-jni/src/main/cpp/src/media/audio/RawAudioFileSource.cpp deleted file mode 100644 index e748faa..0000000 --- a/webrtc-jni/src/main/cpp/src/media/audio/RawAudioFileSource.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/audio/RawAudioFileSource.h" - -#include -#include - -namespace jni -{ - RawAudioFileSource::RawAudioFileSource(std::string fileName) - { - inputStream.open(fileName, std::ofstream::in | std::ofstream::binary); - - // Get length of the file. - inputStream.seekg(0, inputStream.end); - fileLength = inputStream.tellg(); - fileRemainingBytes = fileLength; - inputStream.seekg(0, inputStream.beg); - } - - RawAudioFileSource::~RawAudioFileSource() - { - inputStream.close(); - } - - int32_t RawAudioFileSource::NeedMorePlayData( - const size_t nSamples, - const size_t nBytesPerSample, - const size_t nChannels, - const uint32_t samplesPerSec, - void * audioSamples, - size_t & nSamplesOut, - int64_t * elapsed_time_ms, - int64_t * ntp_time_ms) - { - size_t audioSamplesSize = nSamples * nBytesPerSample; - size_t readBytes = std::min(audioSamplesSize, fileRemainingBytes); - - *elapsed_time_ms = 0; - *ntp_time_ms = 0; - - if (readBytes < nBytesPerSample) { - // EOF. Fill with silence. - nSamplesOut = nSamples; - - std::memset(audioSamples, 0, audioSamplesSize); - - return 0; - } - - nSamplesOut = readBytes / nBytesPerSample; - fileRemainingBytes -= readBytes; - - inputStream.read(static_cast(audioSamples), readBytes); - - return 0; - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/audio/WavAudioFileSink.cpp b/webrtc-jni/src/main/cpp/src/media/audio/WavAudioFileSink.cpp deleted file mode 100644 index 4740968..0000000 --- a/webrtc-jni/src/main/cpp/src/media/audio/WavAudioFileSink.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/audio/WavAudioFileSink.h" - -namespace jni -{ - WavAudioFileSink::WavAudioFileSink(std::string fileName) - { - wavWriter = std::make_unique(fileName, 48000, 2); - } - - WavAudioFileSink::~WavAudioFileSink() - { - } - - int32_t WavAudioFileSink::RecordedDataIsAvailable( - const void * audioSamples, - const size_t nSamples, - const size_t nBytesPerSample, - const size_t nChannels, - const uint32_t samplesPerSec, - const uint32_t totalDelayMS, - const int32_t clockDrift, - const uint32_t currentMicLevel, - const bool keyPressed, - uint32_t & newMicLevel) - { - wavWriter->WriteSamples(static_cast(audioSamples), nSamples * nChannels); - - return 0; - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/audio/WavAudioFileSource.cpp b/webrtc-jni/src/main/cpp/src/media/audio/WavAudioFileSource.cpp deleted file mode 100644 index 15e94ec..0000000 --- a/webrtc-jni/src/main/cpp/src/media/audio/WavAudioFileSource.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/audio/WavAudioFileSource.h" - -#include "rtc_base/logging.h" - -#include -#include - -namespace jni -{ - WavAudioFileSource::WavAudioFileSource(std::string fileName) - { - wavReader = std::make_unique(fileName); - - RTC_LOG(LS_INFO) << "WAV file opened:" - << " Sample Rate: " << wavReader->sample_rate() - << ", Channels: " << wavReader->num_channels() - << ", Samples: " << wavReader->num_samples(); - } - - WavAudioFileSource::~WavAudioFileSource() - { - } - - int32_t WavAudioFileSource::NeedMorePlayData( - const size_t nSamples, - const size_t nBytesPerSample, - const size_t nChannels, - const uint32_t samplesPerSec, - void * audioSamples, - size_t & nSamplesOut, - int64_t * elapsed_time_ms, - int64_t * ntp_time_ms) - { - *elapsed_time_ms = 0; - *ntp_time_ms = 0; - - nSamplesOut = wavReader->ReadSamples(nSamples * nChannels, static_cast(audioSamples)); - - if (nSamplesOut < nSamples) { - // EOF. Fill with silence. - nSamplesOut = nSamples * nChannels; - - std::memset(audioSamples, 0, nSamples * nBytesPerSample); - } - - return 0; - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/audio/linux/PulseAudioDeviceManager.cpp b/webrtc-jni/src/main/cpp/src/media/audio/linux/PulseAudioDeviceManager.cpp deleted file mode 100644 index bcdfd8c..0000000 --- a/webrtc-jni/src/main/cpp/src/media/audio/linux/PulseAudioDeviceManager.cpp +++ /dev/null @@ -1,438 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/audio/linux/PulseAudioDeviceManager.h" -#include "media/audio/linux/PulseAudioLoader.h" -#include "Exception.h" - -namespace jni -{ - namespace avdev - { - PulseAudioDeviceManager::PulseAudioDeviceManager() - { - // Try to load PulseAudio symbols dynamically - if (!PulseAudioLoader::instance().load()) { - throw Exception("PulseAudio: Library not found on system."); - } - - // Use the loader instance for function calls - auto& pa = PulseAudioLoader::instance(); - - mainloop = pa.pa_threaded_mainloop_new(); - - if (mainloop == 0) { - throw Exception("PulseAudio: Could not create threaded mainloop"); - } - - if (pa.pa_threaded_mainloop_start(mainloop) != 0) { - pa.pa_threaded_mainloop_free(mainloop); - - throw Exception("PulseAudio: Could not start threaded mainloop"); - } - - pa_mainloop_api * mainloopApi = pa.pa_threaded_mainloop_get_api(mainloop); - context = pa.pa_context_new(mainloopApi, "MediaDevices"); - - if (!context) { - pa.pa_threaded_mainloop_free(mainloop); - - throw Exception("PulseAudio: Could not create context"); - } - - pa.pa_context_set_state_callback(context, stateCallback, mainloop); - pa.pa_context_set_subscribe_callback(context, subscribeCallback, this); - - pa.pa_threaded_mainloop_lock(mainloop); - - if (pa.pa_context_connect(context, nullptr, PA_CONTEXT_NOFLAGS, nullptr) < 0) { - pa.pa_context_unref(context); - pa.pa_threaded_mainloop_free(mainloop); - - throw Exception("PulseAudio: Could not connect to the context"); - } - - while (true) { - pa_context_state_t contextState = pa.pa_context_get_state(context); - - if (contextState == PA_CONTEXT_FAILED || contextState == PA_CONTEXT_TERMINATED) { - dispose(); - return; - } - if (contextState == PA_CONTEXT_READY) { - break; - } - - pa.pa_threaded_mainloop_wait(mainloop); - } - - int mask = PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE; - - pa_subscription_mask_t mask_t = static_cast(mask); - pa_operation * op = pa.pa_context_subscribe(context, mask_t, nullptr, nullptr); - - pa.pa_threaded_mainloop_unlock(mainloop); - - if (!op) { - throw Exception("PulseAudio: Failed to subscribe context"); - } - pa.pa_operation_unref(op); - } - - PulseAudioDeviceManager::~PulseAudioDeviceManager() - { - dispose(); - } - - void PulseAudioDeviceManager::dispose() - { - auto& pa = PulseAudioLoader::instance(); - - if (!mainloop) { - return; - } - - pa.pa_threaded_mainloop_lock(mainloop); - - if (context) { - pa.pa_context_set_state_callback(context, nullptr, nullptr); - pa.pa_context_disconnect(context); - pa.pa_context_unref(context); - context = nullptr; - } - - pa.pa_threaded_mainloop_stop(mainloop); - pa.pa_threaded_mainloop_free(mainloop); - - mainloop = nullptr; - } - - void PulseAudioDeviceManager::iterate(pa_threaded_mainloop * main_loop, pa_operation * op) { - if (!op) { - throw Exception("PulseAudio: No operation to process"); - } - - auto& pa = PulseAudioLoader::instance(); - - while (pa.pa_operation_get_state(op) == PA_OPERATION_RUNNING) { - pa.pa_threaded_mainloop_wait(main_loop); - } - - pa.pa_operation_unref(op); - } - - AudioDevicePtr PulseAudioDeviceManager::getDefaultAudioCaptureDevice() - { - auto& pa = PulseAudioLoader::instance(); - - if (!pa.pa_threaded_mainloop_in_thread(mainloop)) - pa.pa_threaded_mainloop_lock(mainloop); - - pa_operation * op = pa.pa_context_get_server_info(context, serverInfoCallback, this); - - if (!pa.pa_threaded_mainloop_in_thread(mainloop)) - iterate(mainloop, op); - - op = pa.pa_context_get_source_info_by_name(context, defaultCaptureName.c_str(), getSourceInfoCallback, this); - - if (!pa.pa_threaded_mainloop_in_thread(mainloop)) - iterate(mainloop, op); - - if (!pa.pa_threaded_mainloop_in_thread(mainloop)) - pa.pa_threaded_mainloop_unlock(mainloop); - - AudioDevicePtr defaultDevice = std::make_shared(defaultCaptureDescName, defaultCaptureName); - defaultDevice->directionType = AudioDeviceDirectionType::adtCapture; - return defaultDevice; - } - - std::set PulseAudioDeviceManager::getAudioCaptureDevices() - { - if (!captureDevices.empty()) { - return captureDevices.devices(); - } - - auto& pa = PulseAudioLoader::instance(); - - pa.pa_threaded_mainloop_lock(mainloop); - pa_operation * op = pa.pa_context_get_source_info_list(context, getSourceCallback, this); - iterate(mainloop, op); - pa.pa_threaded_mainloop_unlock(mainloop); - - return captureDevices.devices(); - } - - AudioDevicePtr PulseAudioDeviceManager::getDefaultAudioPlaybackDevice() - { - auto& pa = PulseAudioLoader::instance(); - - if (!pa.pa_threaded_mainloop_in_thread(mainloop)) - pa.pa_threaded_mainloop_lock(mainloop); - - pa_operation * op = pa.pa_context_get_server_info(context, serverInfoCallback, this); - - if (!pa.pa_threaded_mainloop_in_thread(mainloop)) - iterate(mainloop, op); - - op = pa.pa_context_get_sink_info_by_name(context, defaultPlaybackName.c_str(), getSinkInfoCallback, this); - - if (!pa.pa_threaded_mainloop_in_thread(mainloop)) - iterate(mainloop, op); - - if (!pa.pa_threaded_mainloop_in_thread(mainloop)) - pa.pa_threaded_mainloop_unlock(mainloop); - - AudioDevicePtr defaultDevice = std::make_shared(defaultPlaybackDescName, defaultPlaybackName); - defaultDevice->directionType = AudioDeviceDirectionType::adtRender; - return defaultDevice; - } - - std::set PulseAudioDeviceManager::getAudioPlaybackDevices() - { - if (!playbackDevices.empty()) { - return playbackDevices.devices(); - } - - auto& pa = PulseAudioLoader::instance(); - - pa.pa_threaded_mainloop_lock(mainloop); - pa_operation * op = pa.pa_context_get_sink_info_list(context, getSinkCallback, this); - iterate(mainloop, op); - pa.pa_threaded_mainloop_unlock(mainloop); - - return playbackDevices.devices(); - } - - void PulseAudioDeviceManager::getSourceInfoCallback(pa_context * ctx, const pa_source_info * info, int last, void * userdata) - { - PulseAudioDeviceManager * engine = reinterpret_cast(userdata); - - auto& pa = PulseAudioLoader::instance(); - - if (last > 0) { - pa.pa_threaded_mainloop_signal(engine->mainloop, 0); - return; - } - - engine->defaultCaptureDescName = info->description; - } - - void PulseAudioDeviceManager::getSourceCallback(pa_context * ctx, const pa_source_info * info, int last, void * userdata) - { - PulseAudioDeviceManager * engine = reinterpret_cast(userdata); - - if (last) { - auto& pa = PulseAudioLoader::instance(); - pa.pa_threaded_mainloop_signal(engine->mainloop, 0); - return; - } - - if (info->monitor_of_sink == PA_INVALID_INDEX) { - engine->insertDevice(engine->captureDevices, info->proplist, info->description, info->name, info->index, false, true); - } - } - - void PulseAudioDeviceManager::newSourceCallback(pa_context * ctx, const pa_source_info * info, int last, void * userdata) - { - PulseAudioDeviceManager * engine = reinterpret_cast(userdata); - - if (last) { - auto& pa = PulseAudioLoader::instance(); - pa.pa_threaded_mainloop_signal(engine->mainloop, 0); - return; - } - - engine->insertDevice(engine->captureDevices, info->proplist, info->description, info->name, info->index, true, true); - } - - void PulseAudioDeviceManager::getSinkInfoCallback(pa_context * ctx, const pa_sink_info * info, int last, void * userdata) - { - PulseAudioDeviceManager * engine = reinterpret_cast(userdata); - - if (last > 0) { - auto& pa = PulseAudioLoader::instance(); - pa.pa_threaded_mainloop_signal(engine->mainloop, 0); - return; - } - - engine->defaultPlaybackDescName = info->description; - } - - void PulseAudioDeviceManager::getSinkCallback(pa_context * ctx, const pa_sink_info * info, int last, void * userdata) - { - PulseAudioDeviceManager * engine = reinterpret_cast(userdata); - - if (last) { - auto& pa = PulseAudioLoader::instance(); - pa.pa_threaded_mainloop_signal(engine->mainloop, 0); - return; - } - - engine->insertDevice(engine->playbackDevices, info->proplist, info->description, info->name, info->index, false, false); - } - - void PulseAudioDeviceManager::newSinkCallback(pa_context * ctx, const pa_sink_info * info, int last, void * userdata) - { - PulseAudioDeviceManager * engine = reinterpret_cast(userdata); - - if (last) { - auto& pa = PulseAudioLoader::instance(); - pa.pa_threaded_mainloop_signal(engine->mainloop, 0); - return; - } - - engine->insertDevice(engine->playbackDevices, info->proplist, info->description, info->name, info->index, true, false); - } - - void PulseAudioDeviceManager::insertDevice(DeviceList & devices, pa_proplist * proplist, const char * name, const char * desc, uint32_t index, bool notify, bool isCapture) - { - auto device = std::make_shared(name, desc); - - if (devices.insertDevice(device)) { - if (isCapture) { - device->directionType = AudioDeviceDirectionType::adtCapture; - } else { - device->directionType = AudioDeviceDirectionType::adtRender; - } - fillAdditionalTypes(device, proplist); - deviceMap[index] = device; - } - if (notify) { - notifyDeviceConnected(device); - } - } - - void PulseAudioDeviceManager::removeDevice(DeviceList & devices, uint32_t index, bool isCapture) - { - auto it = deviceMap.find(index); - if (it == deviceMap.end()) { - return; - } - - if (devices.removeDevice(it->second)) { - if (isCapture) { - it->second->directionType = AudioDeviceDirectionType::adtCapture; - } else { - it->second->directionType = AudioDeviceDirectionType::adtRender; - } - - notifyDeviceDisconnected(it->second); - deviceMap.erase(it); - } - } - - void PulseAudioDeviceManager::stateCallback(pa_context * ctx, void * userdata) - { - auto& pa = PulseAudioLoader::instance(); - pa_threaded_mainloop * mainloop = static_cast(userdata); - pa.pa_threaded_mainloop_signal(mainloop, 0); - } - - void PulseAudioDeviceManager::serverInfoCallback(pa_context * ctx, const pa_server_info * info, void * userdata) - { - auto& pa = PulseAudioLoader::instance(); - - PulseAudioDeviceManager * engine = reinterpret_cast(userdata); - engine->defaultCaptureName = info->default_source_name; - engine->defaultPlaybackName = info->default_sink_name; - - pa.pa_threaded_mainloop_signal(engine->mainloop, 0); - } - - void PulseAudioDeviceManager::subscribeCallback(pa_context * ctx, pa_subscription_event_type_t type, uint32_t idx, void * userdata) - { - PulseAudioDeviceManager * engine = reinterpret_cast(userdata); - unsigned facility = type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK; - unsigned operation = type & PA_SUBSCRIPTION_EVENT_TYPE_MASK; - pa_operation * op = nullptr; - auto& pa = PulseAudioLoader::instance(); - - if (facility == PA_SUBSCRIPTION_EVENT_SOURCE) { - if (operation == PA_SUBSCRIPTION_EVENT_NEW) { - op = pa.pa_context_get_source_info_by_index(ctx, idx, newSourceCallback, engine); - } - if (operation == PA_SUBSCRIPTION_EVENT_REMOVE) { - engine->removeDevice(engine->captureDevices, idx, true); - } - } - if (facility == PA_SUBSCRIPTION_EVENT_SINK) { - if (operation == PA_SUBSCRIPTION_EVENT_NEW) { - op = pa.pa_context_get_sink_info_by_index(ctx, idx, newSinkCallback, engine); - } - if (operation == PA_SUBSCRIPTION_EVENT_REMOVE) { - engine->removeDevice(engine->playbackDevices, idx, false); - } - } - - if (op) { - pa.pa_operation_unref(op); - } - } - - void PulseAudioDeviceManager::fillAdditionalTypes(AudioDevicePtr device, pa_proplist * proplist) { - // all property values see here https://docs.rs/libpulse-sys/latest/libpulse_sys/proplist/ - const char *formFactor; - auto& pa = PulseAudioLoader::instance(); - formFactor = pa.pa_proplist_gets(proplist, PA_PROP_DEVICE_FORM_FACTOR); - std::string formFactorStr = ""; - if (formFactor) { - formFactorStr = std::string(formFactor); - } - - const char *deviceTransport; - deviceTransport = pa.pa_proplist_gets(proplist, PA_PROP_DEVICE_BUS); - std::string deviceTransportStr = ""; - if (deviceTransport) { - deviceTransportStr = std::string(deviceTransport); - } - - const char *propHDMI; - propHDMI = pa.pa_proplist_gets(proplist, PA_PROP_DEVICE_BUS_PATH); - if (propHDMI && std::string(propHDMI).find("_hdmi") != std::string::npos) { - deviceTransportStr = "hdmi"; - } - - device->setDeviceFormFactor(getActualFormFactor(formFactorStr)); - device->setDeviceTransport(getActualTransport(deviceTransportStr)); - } - - DeviceFormFactor PulseAudioDeviceManager::getActualFormFactor(std::string formFactor) { - if (formFactor == "speaker") { - return DeviceFormFactor::ffSpeaker; - } else if (formFactor == "microphone") { - return DeviceFormFactor::ffMicrophone; - } else if (formFactor == "headset") { - return DeviceFormFactor::ffHeadset; - } else if (formFactor == "headphone") { - return DeviceFormFactor::ffHeadphone; - } - - return DeviceFormFactor::ffUnknown; - } - - DeviceTransport PulseAudioDeviceManager::getActualTransport(std::string transport) { - if (transport == "usb") { - return DeviceTransport::trUsb; - } else if (transport == "bluetooth") { - return DeviceTransport::trWireless; - } else if (transport == "hdmi") { - return DeviceTransport::trHdmi; - } - - return DeviceTransport::trUnknown; - } - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/audio/macos/CoreAudioDeviceManager.cpp b/webrtc-jni/src/main/cpp/src/media/audio/macos/CoreAudioDeviceManager.cpp deleted file mode 100644 index cb6e12e..0000000 --- a/webrtc-jni/src/main/cpp/src/media/audio/macos/CoreAudioDeviceManager.cpp +++ /dev/null @@ -1,480 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/audio/macos/CoreAudioDeviceManager.h" -#include "platform/macos/MacUtils.h" - -#include "rtc_base/logging.h" - -#include -#include - -#if !defined(MAC_OS_VERSION_12_0) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_VERSION_12_0 - #define kAudioObjectPropertyElementMain kAudioObjectPropertyElementMaster -#endif - -namespace jni -{ - namespace avdev - { - CoreAudioDeviceManager::CoreAudioDeviceManager() : - AudioDeviceManager() - { - AudioObjectPropertyAddress pa; - pa.mSelector = kAudioObjectPropertySelectorWildcard; - pa.mScope = kAudioObjectPropertyScopeWildcard; - pa.mElement = kAudioObjectPropertyElementWildcard; - - OSStatus status = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &pa, deviceListenerProc, this); - ThrowIfFailed(status, "CoreAudio: Add device listener failed"); - } - - CoreAudioDeviceManager::~CoreAudioDeviceManager() - { - AudioObjectPropertyAddress pa; - pa.mSelector = kAudioObjectPropertySelectorWildcard; - pa.mScope = kAudioObjectPropertyScopeWildcard; - pa.mElement = kAudioObjectPropertyElementWildcard; - - AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &pa, deviceListenerProc, this); - } - - std::set CoreAudioDeviceManager::getAudioCaptureDevices() - { - if (captureDevices.empty()) { - enumerateDevices(kAudioObjectPropertyScopeInput); - } - - return captureDevices.devices(); - } - - std::set CoreAudioDeviceManager::getAudioPlaybackDevices() - { - if (playbackDevices.empty()) { - enumerateDevices(kAudioObjectPropertyScopeOutput); - } - - return playbackDevices.devices(); - } - - AudioDevicePtr CoreAudioDeviceManager::getDefaultAudioCaptureDevice() - { - return createDefaultAudioDevice(kAudioObjectPropertyScopeInput); - } - - AudioDevicePtr CoreAudioDeviceManager::getDefaultAudioPlaybackDevice() - { - return createDefaultAudioDevice(kAudioObjectPropertyScopeOutput); - } - - void CoreAudioDeviceManager::enumerateDevices(const AudioObjectPropertyScope & scope) { - // Get all devices. - AudioObjectPropertyAddress pa; - pa.mSelector = kAudioHardwarePropertyDevices; - pa.mScope = kAudioObjectPropertyScopeGlobal; - pa.mElement = kAudioObjectPropertyElementMain; - - UInt32 dataSize; - - OSStatus status = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &pa, 0, nullptr, &dataSize); - ThrowIfFailed(status, "CoreAudio: Enumerate audio endpoints failed"); - - const int numDevices = dataSize / sizeof(AudioDeviceID); - AudioDeviceID * devIDs = new AudioDeviceID[numDevices]; - - status = AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa, 0, nullptr, &dataSize, devIDs); - ThrowIfFailed(status, "CoreAudio: Enumerate audio endpoints failed"); - - AudioDeviceID defaultID = getDefaultDeviceID(scope); - - for (int i = 0; i < numDevices; i++) { - AudioDevicePtr device = createAudioDevice(devIDs[i], scope); - - if (device != nullptr) { - insertAudioDevice(device, scope); - - // Set default device. - bool isDefault = (defaultID == devIDs[i]); - - if (isDefault && scope == kAudioObjectPropertyScopeInput) { - setDefaultCaptureDevice(device); - } - else if (isDefault && scope == kAudioObjectPropertyScopeOutput) { - setDefaultPlaybackDevice(device); - } - } - } - - delete[] devIDs; - } - - void CoreAudioDeviceManager::onDevicesChanged() - { - // Get all devices. - AudioObjectPropertyAddress pa; - pa.mSelector = kAudioHardwarePropertyDevices; - pa.mScope = kAudioObjectPropertyScopeGlobal; - pa.mElement = kAudioObjectPropertyElementMain; - - UInt32 dataSize; - - OSStatus status = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &pa, 0, nullptr, &dataSize); - ThrowIfFailed(status, "CoreAudio: Enumerate audio endpoints failed"); - - const int numDevices = dataSize / sizeof(AudioDeviceID); - AudioDeviceID * devIDs = new AudioDeviceID[numDevices]; - - status = AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa, 0, nullptr, &dataSize, devIDs); - ThrowIfFailed(status, "CoreAudio: Enumerate audio endpoints failed"); - - // Check, if a new device is available. - for (int i = 0; i < numDevices; i++) { - bool found = false; - - for (const AudioDevicePtr & dev : captureDevices.devices()) { - AudioDeviceID devID = std::stoi(dev->getDescriptor()); - - if (devIDs[i] == devID) { - found = true; - break; - } - } - - for (const AudioDevicePtr & dev : playbackDevices.devices()) { - AudioDeviceID devID = std::stoi(dev->getDescriptor()); - - if (devIDs[i] == devID) { - found = true; - break; - } - } - - if (!found) { - // New device found. - unsigned inChannels = getChannelCount(devIDs[i], kAudioObjectPropertyScopeInput); - unsigned outChannels = getChannelCount(devIDs[i], kAudioObjectPropertyScopeOutput); - - if (inChannels > 0) { - AudioObjectPropertyScope scope = kAudioObjectPropertyScopeInput; - AudioDevicePtr device = createAudioDevice(devIDs[i], scope); - - if (device != nullptr) { - insertAudioDevice(device, scope); - - // Update default capture device. - AudioDevicePtr def = getDefaultCaptureDevice(); - onDefaultDeviceChanged(scope, captureDevices, def); - - notifyDeviceConnected(device); - } - } - if (outChannels > 0) { - AudioObjectPropertyScope scope = kAudioObjectPropertyScopeOutput; - AudioDevicePtr device = createAudioDevice(devIDs[i], scope); - - if (device != nullptr) { - insertAudioDevice(device, scope); - - // Update default playback device. - AudioDevicePtr def = getDefaultPlaybackDevice(); - onDefaultDeviceChanged(scope, playbackDevices, def); - - notifyDeviceConnected(device); - } - } - } - } - - // Check, if a device was disconnected. - checkDeviceGone(captureDevices, devIDs, numDevices, kAudioObjectPropertyScopeInput); - checkDeviceGone(playbackDevices, devIDs, numDevices, kAudioObjectPropertyScopeOutput); - - delete[] devIDs; - } - - void CoreAudioDeviceManager::onDefaultDeviceChanged(const AudioObjectPropertyScope & scope, DeviceList & devices, const AudioDevicePtr & device) - { - AudioDeviceID defaultID = getDefaultDeviceID(scope); - AudioDeviceID deviceID = (device == nullptr) ? 0 : std::stoi(device->getDescriptor()); - - if (defaultID != deviceID) { - auto predicate = [defaultID](const AudioDevicePtr & dev) { - AudioDeviceID devID = std::stoi(dev->getDescriptor()); - - return defaultID == devID; - }; - - AudioDevicePtr found = devices.findDevice(predicate); - - if (found == nullptr) { - RTC_LOG(LS_WARNING) << "CoreAudio: Find device failed"; - return; - } - - if (scope == kAudioObjectPropertyScopeInput) { - found->directionType = AudioDeviceDirectionType::adtCapture; - setDefaultCaptureDevice(found); - } - else if (scope == kAudioObjectPropertyScopeOutput) { - found->directionType = AudioDeviceDirectionType::adtRender; - setDefaultPlaybackDevice(found); - } - } - } - - void CoreAudioDeviceManager::checkDeviceGone(DeviceList & devices, AudioDeviceID * devIDs, const int numDevIDs, const AudioObjectPropertyScope & scope) - { - auto predicate = [devIDs, numDevIDs](const AudioDevicePtr & dev) { - AudioDeviceID devID = std::stoi(dev->getDescriptor()); - bool found = false; - - for (int i = 0; i < numDevIDs; i++) { - if (devIDs[i] == devID) { - found = true; - break; - } - } - - return !found; - }; - - AudioDevicePtr removed = devices.removeDevice(predicate); - - if (removed != nullptr) { - if (scope == kAudioObjectPropertyScopeInput) { - AudioDevicePtr def = getDefaultAudioCaptureDevice(); - - if (removed == def) { - onDefaultDeviceChanged(scope, captureDevices, def); - } - removed->directionType = AudioDeviceDirectionType::adtCapture; - } - else if (scope == kAudioObjectPropertyScopeOutput) { - AudioDevicePtr def = getDefaultAudioPlaybackDevice(); - - if (removed == def) { - onDefaultDeviceChanged(scope, playbackDevices, def); - } - removed->directionType = AudioDeviceDirectionType::adtRender; - } - - notifyDeviceDisconnected(removed); - } - } - - AudioDevicePtr CoreAudioDeviceManager::createDefaultAudioDevice(const AudioObjectPropertyScope & scope) - { - AudioDeviceID defaultID = getDefaultDeviceID(scope); - - return createAudioDevice(defaultID, scope); - } - - AudioDevicePtr CoreAudioDeviceManager::createAudioDevice(const AudioDeviceID & deviceID, const AudioObjectPropertyScope & scope) { - AudioDevicePtr device = nullptr; - CFStringRef devNameRef = nullptr; - UInt32 dataSize = sizeof(devNameRef); - - AudioObjectPropertyAddress pa; - pa.mSelector = kAudioObjectPropertyName; - pa.mScope = kAudioObjectPropertyScopeGlobal; - pa.mElement = kAudioObjectPropertyElementMain; - - OSStatus status = AudioObjectGetPropertyData(deviceID, &pa, 0, nullptr, &dataSize, &devNameRef); - ThrowIfFailed(status, "CoreAudio: Get device name failed"); - - std::string name = CFStringRefToUTF8(devNameRef); - std::string id = std::to_string(deviceID); - - CFRelease(devNameRef); - - unsigned channels = getChannelCount(deviceID, scope); - - if (channels > 0) { - if (scope == kAudioObjectPropertyScopeOutput) { - device = std::make_shared(name, id); - device-> directionType = AudioDeviceDirectionType::adtRender; - } - else if (scope == kAudioObjectPropertyScopeInput) { - device = std::make_shared(name, id); - device->directionType = AudioDeviceDirectionType::adtCapture; - } - fillAdditionalTypes(deviceID, scope, device); - } - - return device; - } - - bool CoreAudioDeviceManager::insertAudioDevice(const AudioDevicePtr & device, const AudioObjectPropertyScope & scope) - { - if (device == nullptr) { - return false; - } - - if (scope == kAudioObjectPropertyScopeOutput) { - device->directionType = AudioDeviceDirectionType::adtRender; - return playbackDevices.insertDevice(device); - } - else if (scope == kAudioObjectPropertyScopeInput) { - device->directionType = AudioDeviceDirectionType::adtCapture; - return captureDevices.insertDevice(device); - } - - return false; - } - - int CoreAudioDeviceManager::getChannelCount(const AudioDeviceID & deviceID, const AudioObjectPropertyScope & scope) { - AudioObjectPropertyAddress pa; - pa.mSelector = kAudioDevicePropertyStreamConfiguration; - pa.mElement = kAudioObjectPropertyElementMain; - pa.mScope = scope; - - int channels = 0; - UInt32 dataSize; - - if (AudioObjectGetPropertyDataSize(deviceID, &pa, 0, nullptr, &dataSize) == noErr) { - AudioBufferList * buffers = new AudioBufferList[dataSize]; - - if (AudioObjectGetPropertyData(deviceID, &pa, 0, nullptr, &dataSize, buffers) == noErr) { - for (int i = 0; i < buffers->mNumberBuffers; i++) { - channels += buffers->mBuffers[i].mNumberChannels; - } - } - - delete[] buffers; - } - - return channels; - } - - AudioDeviceID CoreAudioDeviceManager::getDefaultDeviceID(const AudioObjectPropertyScope & scope) { - AudioObjectPropertyAddress pa; - pa.mScope = kAudioObjectPropertyScopeGlobal; - pa.mElement = kAudioObjectPropertyElementMain; - - switch (scope) { - case kAudioObjectPropertyScopeInput: - pa.mSelector = kAudioHardwarePropertyDefaultInputDevice; - break; - - case kAudioObjectPropertyScopeOutput: - pa.mSelector = kAudioHardwarePropertyDefaultOutputDevice; - break; - } - - AudioDeviceID defaultID = 0; - UInt32 dataSize = sizeof(AudioDeviceID); - OSStatus status = AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa, 0, nullptr, &dataSize, &defaultID); - - if (status != noErr) { - RTC_LOG(LS_ERROR) << "CoreAudio: Get default device ID failed: Status = " << status; - } - - return defaultID; - } - - OSStatus CoreAudioDeviceManager::deviceListenerProc(AudioObjectID objectID, UInt32 numberAddresses, const AudioObjectPropertyAddress addresses[], void * clientData) { - CoreAudioDeviceManager * manager = static_cast(clientData); - - for (int i = 0; i < numberAddresses; i++) { - switch (addresses[i].mSelector) { - case kAudioHardwarePropertyDevices: - { - manager->onDevicesChanged(); - break; - } - - case kAudioHardwarePropertyDefaultInputDevice: - { - AudioDevicePtr def = manager->getDefaultCaptureDevice(); - manager->onDefaultDeviceChanged(kAudioObjectPropertyScopeInput, manager->captureDevices, def); - break; - } - - case kAudioHardwarePropertyDefaultOutputDevice: - { - AudioDevicePtr defp = manager->getDefaultPlaybackDevice(); - manager->onDefaultDeviceChanged(kAudioObjectPropertyScopeOutput, manager->playbackDevices, defp); - break; - } - } - } - - return noErr; - } - - void CoreAudioDeviceManager::fillAdditionalTypes(const AudioDeviceID & deviceID, const AudioObjectPropertyScope & scope, AudioDevicePtr device) { - // Get Transport Type - AudioObjectPropertyAddress address = { - kAudioDevicePropertyTransportType, - scope, - kAudioObjectPropertyElementMaster - }; - unsigned int transportType = 0; - UInt32 size = 0; - size = sizeof(transportType); - OSStatus status = AudioObjectGetPropertyData(deviceID, &address, 0, nullptr, &size, &transportType); - // Get Transport Type -- end - - address.mSelector = kAudioDevicePropertyDataSource; - UInt32 sourceCode = 0; - size = sizeof(UInt32); - status = AudioObjectGetPropertyData(deviceID, &address, 0, nullptr, &size, &sourceCode); - - device->setDeviceTransport(getActualTransport(transportType)); - device->setDeviceFormFactor(getActualFormFactor(sourceCode)); - } - - DeviceFormFactor CoreAudioDeviceManager::getActualFormFactor(const unsigned int sourceID) { - switch(sourceID) { - case kIOAudioOutputPortSubTypeInternalSpeaker: - case kIOAudioOutputPortSubTypeExternalSpeaker: - return DeviceFormFactor::ffSpeaker; - case kIOAudioOutputPortSubTypeHeadphones: - return DeviceFormFactor::ffHeadphone; - case kIOAudioInputPortSubTypeInternalMicrophone: - case kIOAudioInputPortSubTypeExternalMicrophone: - return DeviceFormFactor::ffMicrophone; - case kIOAudioInputPortSubTypeCD: - case kIOAudioOutputPortSubTypeSPDIF: - case kIOAudioOutputPortSubTypeLine: - return DeviceFormFactor::ffUnknown; - default: - return DeviceFormFactor::ffUnknown; - } - } - - DeviceTransport CoreAudioDeviceManager::getActualTransport(const unsigned int transportType) { - switch(transportType) { - case kAudioDeviceTransportTypeUSB: - return DeviceTransport::trUsb; - case kAudioDeviceTransportTypeBluetooth: - return DeviceTransport::trWireless; - case kAudioDeviceTransportTypeHDMI: - return DeviceTransport::trHdmi; - case kAudioDeviceTransportTypeFireWire: - case kAudioDeviceTransportTypeDisplayPort: - case kAudioDeviceTransportTypePCI: - case kAudioDeviceTransportTypeVirtual: - case kAudioDeviceTransportTypeAutoAggregate: - case kAudioDeviceTransportTypeBuiltIn: - case kAudioDeviceTransportTypeUnknown: - return DeviceTransport::trUnknown; - default: - return DeviceTransport::trUnknown; - } - } - } -} diff --git a/webrtc-jni/src/main/cpp/src/media/audio/windows/WindowsAudioDeviceManager.cpp b/webrtc-jni/src/main/cpp/src/media/audio/windows/WindowsAudioDeviceManager.cpp deleted file mode 100644 index 705d8dd..0000000 --- a/webrtc-jni/src/main/cpp/src/media/audio/windows/WindowsAudioDeviceManager.cpp +++ /dev/null @@ -1,488 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "Exception.h" -#include "media/audio/windows/WindowsAudioDeviceManager.h" -#include "platform/windows/MFInitializer.h" -#include "platform/windows/WinUtils.h" -#include "WebRTCContext.h" - -#include "Functiondiscoverykeys_devpkey.h" - -#include "api/audio/create_audio_device_module.h" -#include "api/scoped_refptr.h" -#include "modules/audio_device/include/audio_device.h" -#include "rtc_base/logging.h" - -#include - -namespace jni -{ - namespace avdev - { - WindowsAudioDeviceManager::WindowsAudioDeviceManager() : - deviceEnumerator() - { - HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&deviceEnumerator); - THROW_IF_FAILED(hr, "MMF: Create device enumerator failed"); - - deviceEnumerator->RegisterEndpointNotificationCallback(this); - } - - WindowsAudioDeviceManager::~WindowsAudioDeviceManager() - { - if (deviceEnumerator) { - deviceEnumerator->UnregisterEndpointNotificationCallback(this); - } - } - - AudioDevicePtr WindowsAudioDeviceManager::getDefaultAudioCaptureDevice() - { - return createDefaultAudioDevice(EDataFlow::eCapture); - } - - AudioDevicePtr WindowsAudioDeviceManager::getDefaultAudioPlaybackDevice() - { - return createDefaultAudioDevice(EDataFlow::eRender); - } - - std::set WindowsAudioDeviceManager::getAudioCaptureDevices() - { - if (!comInitializer.isInitialized()) { - throw jni::Exception("Invalid COM thread model change (MTA->STA)"); - } - - if (captureDevices.empty()) { - enumerateDevices(eCapture); - } - - return captureDevices.devices(); - } - - std::set WindowsAudioDeviceManager::getAudioPlaybackDevices() - { - if (!comInitializer.isInitialized()) { - throw jni::Exception("Invalid COM thread model change (MTA->STA)"); - } - - if (playbackDevices.empty()) { - enumerateDevices(eRender); - } - - return playbackDevices.devices(); - } - - void WindowsAudioDeviceManager::enumerateDevices(EDataFlow dataFlow) - { - jni::WebRTCContext * context = static_cast(javaContext); - - webrtc::scoped_refptr audioModule = webrtc::CreateAudioDeviceModule( - context->webrtcEnv, webrtc::AudioDeviceModule::kPlatformDefaultAudio); - - if (!audioModule) { - throw jni::Exception("Create AudioDeviceModule failed"); - } - if (audioModule->Init() != 0) { - throw jni::Exception("Initialize AudioDeviceModule failed"); - } - - bool enumCaptureDevices = false; - bool enumRenderDevices = false; - - if (dataFlow == EDataFlow::eAll || dataFlow == EDataFlow::eCapture) { - enumCaptureDevices = true; - } - if (dataFlow == EDataFlow::eAll || dataFlow == EDataFlow::eRender) { - enumRenderDevices = true; - } - - char name[webrtc::kAdmMaxDeviceNameSize]; - char guid[webrtc::kAdmMaxGuidSize]; - - if (enumCaptureDevices) { - int16_t deviceCount = audioModule->RecordingDevices(); - // fix duplicated item when device reconect to port. The comparator does not always work correctly. - if (deviceCount > 0) { - captureDevices.clearDevices(); - } - - for (int i = 0; i < deviceCount; ++i) { - if (audioModule->RecordingDeviceName(i, name, guid) == 0) { - AudioDevicePtr device = std::make_shared(name, guid); - - fillAdditionalTypes(device); - - insertAudioDevice(device, EDataFlow::eCapture); - } - } - } - if (enumRenderDevices) { - int16_t deviceCount = audioModule->PlayoutDevices(); - - // Fix duplicated item when device reconect to port. The comparator does not always work correctly. - if (deviceCount > 0) { - playbackDevices.clearDevices(); - } - - for (int i = 0; i < deviceCount; ++i) { - if (audioModule->PlayoutDeviceName(i, name, guid) == 0) { - AudioDevicePtr device = std::make_shared(name, guid); - - fillAdditionalTypes(device); - - insertAudioDevice(device, EDataFlow::eRender); - } - } - } - } - - void WindowsAudioDeviceManager::fillAdditionalTypes(AudioDevicePtr device) - { - MFInitializer initializer; - ComPtr pDevice; - ComPtr endpoint; - ComPtr propertyStore; - HRESULT hr; - PROPVARIANT ff; - PropVariantInit(&ff); - - // convert std::string to LPWSTR - wchar_t* wDeviceID=new wchar_t[4096]; - size_t convertedChars = 0; - mbstowcs_s(&convertedChars, wDeviceID, device->getDescriptor().length() + 1, device->getDescriptor().c_str(), _TRUNCATE); - - hr = deviceEnumerator->GetDevice(wDeviceID, &pDevice); - delete[] wDeviceID; - - THROW_IF_FAILED(hr, "Audio Device Manager: Enumerator get device with ID: %S failed", device->getDescriptor().c_str()); - - hr = pDevice->QueryInterface(__uuidof(IMMEndpoint), (void**)&endpoint); - THROW_IF_FAILED(hr, "Audio Device Manager: Device get endpoint failed"); - - hr = pDevice->OpenPropertyStore(STGM_READ, &propertyStore); - THROW_IF_FAILED(hr, "Audio Device Manager: Device open property store failed"); - - hr = propertyStore->GetValue(PKEY_AudioEndpoint_FormFactor, &ff); - THROW_IF_FAILED(hr, "Audio Device Manager: PropertyStore get form factor property name failed"); - - EndpointFormFactor formFactor = static_cast(ff.uintVal); - PropVariantClear(&ff); - - device->setDeviceTransport(getActualTransport(formFactor)); - device->setDeviceFormFactor(getActualFormFactor(formFactor)); - } - - void WindowsAudioDeviceManager::addDevice(LPCWSTR deviceId) - { - if (deviceId == nullptr) { - return; - } - - EDataFlow dataFlow; - std::shared_ptr device = createAudioDevice(deviceId, &dataFlow); - bool inserted = insertAudioDevice(device, dataFlow); - - if (inserted) { - notifyDeviceConnected(device); - } - } - - void WindowsAudioDeviceManager::removeDevice(LPCWSTR deviceId) - { - if (deviceId == nullptr) - return; - - std::string id = WideStrToStr(deviceId); - - removeAudioDevice(captureDevices, id, eCapture); - removeAudioDevice(playbackDevices, id, eRender); - } - - AudioDevicePtr WindowsAudioDeviceManager::createDefaultAudioDevice(const EDataFlow& dataFlow) - { - MFInitializer initializer; - ComPtr deviceCollection; - ComPtr defaultDevice; - ComPtr propertyStore; - LPWSTR defaultDeviceId = nullptr; - PROPVARIANT pv; - PropVariantInit(&pv); - - HRESULT hr = deviceEnumerator->GetDefaultAudioEndpoint(dataFlow, eMultimedia, &defaultDevice); - THROW_IF_FAILED(hr, "MMF: Get default audio endpoint failed"); - - hr = defaultDevice->GetId(&defaultDeviceId); - THROW_IF_FAILED(hr, "MMF: Get default device ID failed"); - - hr = defaultDevice->OpenPropertyStore(STGM_READ, &propertyStore); - THROW_IF_FAILED(hr, "MMF: Device open property store failed"); - - hr = propertyStore->GetValue(PKEY_Device_FriendlyName, &pv); - THROW_IF_FAILED(hr, "MMF: PropertyStore get friendly name failed"); - - std::string id = WideStrToStr(defaultDeviceId); - std::string name = WideStrToStr(pv.pwszVal); - - AudioDevicePtr device = std::make_shared(name, id); - if (dataFlow == eCapture) { - device->directionType = AudioDeviceDirectionType::adtCapture; - } else { - device->directionType = AudioDeviceDirectionType::adtRender; - } - - fillAdditionalTypes(device); - - PropVariantClear(&pv); - - return device; - } - - AudioDevicePtr WindowsAudioDeviceManager::createAudioDevice(LPCWSTR deviceId, EDataFlow * dataFlow) - { - MFInitializer initializer; - ComPtr pDevice; - ComPtr endpoint; - ComPtr propertyStore; - EDataFlow flow; - PROPVARIANT pv; - PropVariantInit(&pv); - HRESULT hr; - - hr = deviceEnumerator->GetDevice(deviceId, &pDevice); - THROW_IF_FAILED(hr, "MMF: Enumerator get device with ID: %S failed", deviceId); - - hr = pDevice->QueryInterface(__uuidof(IMMEndpoint), (void**)&endpoint); - THROW_IF_FAILED(hr, "MMF: Device get endpoint failed"); - - hr = endpoint->GetDataFlow(&flow); - THROW_IF_FAILED(hr, "MMF: Endpoint get data flow failed"); - - hr = pDevice->OpenPropertyStore(STGM_READ, &propertyStore); - THROW_IF_FAILED(hr, "MMF: Device open property store failed"); - - hr = propertyStore->GetValue(PKEY_Device_FriendlyName, &pv); - THROW_IF_FAILED(hr, "MMF: PropertyStore get friendly name failed"); - - std::string id = WideStrToStr(deviceId); - std::string name = WideStrToStr(pv.pwszVal); - - AudioDevicePtr device = std::make_shared(name, id); - - fillAdditionalTypes(device); - - if (dataFlow != nullptr) { - *dataFlow = flow; - } - - PropVariantClear(&pv); - - return device; - } - - bool WindowsAudioDeviceManager::insertAudioDevice(AudioDevicePtr device, EDataFlow dataFlow) - { - if (device == nullptr) { - return false; - } - - if (dataFlow == eCapture) { - device->directionType = jni::avdev::AudioDeviceDirectionType::adtCapture; - - captureDevices.insertDevice(device); - return true; - } - else if (dataFlow == eRender) { - device->directionType = jni::avdev::AudioDeviceDirectionType::adtRender; - - playbackDevices.insertDevice(device); - return true; - } - - return false; - } - - void WindowsAudioDeviceManager::removeAudioDevice(DeviceList & devices, std::string id, EDataFlow dataFlow) - { - auto predicate = [id](const AudioDevicePtr & dev) { - return id == dev->getDescriptor(); - }; - - AudioDevicePtr removed = devices.removeDevice(predicate); - - if (removed) { - if (dataFlow == eCapture) { - removed->directionType = AudioDeviceDirectionType::adtCapture; - } else { - removed->directionType = AudioDeviceDirectionType::adtRender; - } - - notifyDeviceDisconnected(removed); - } - } - - ULONG WindowsAudioDeviceManager::AddRef() - { - return 1; - } - - ULONG WindowsAudioDeviceManager::Release() - { - return 1; - } - - HRESULT WindowsAudioDeviceManager::QueryInterface(REFIID iid, void ** object) - { - if (object == nullptr) { - return E_POINTER; - } - - if (iid == IID_IUnknown || iid == __uuidof(IMMNotificationClient)) { - *object = static_cast(this); - } - else { - *object = nullptr; - return E_NOINTERFACE; - } - - AddRef(); - - return S_OK; - } - - HRESULT WindowsAudioDeviceManager::OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR deviceId) - { - RTC_LOG(LS_INFO) << "MMF: Default device changed (" << RoleToStr(role).c_str() << "): " << deviceId; - - std::string id; - - if (deviceId != nullptr) { - id = WideStrToStr(deviceId); - } - - auto predicate = [id](const AudioDevicePtr & dev) { - return id == dev->getDescriptor(); - }; - - if (flow == eCapture) { - if (deviceId == nullptr) { - setDefaultCaptureDevice(nullptr); - return S_OK; - } - - AudioDevicePtr found = captureDevices.findDevice(predicate); - - if (found) { - setDefaultCaptureDevice(found); - } - } - else if (flow == eRender) { - if (deviceId == nullptr) { - setDefaultPlaybackDevice(nullptr); - return S_OK; - } - - AudioDevicePtr found = playbackDevices.findDevice(predicate); - - if (found) { - setDefaultPlaybackDevice(found); - } - } - - return S_OK; - } - - HRESULT WindowsAudioDeviceManager::OnDeviceAdded(LPCWSTR deviceId) - { - RTC_LOG(LS_INFO) << "MMF: Device added: " << deviceId; - - addDevice(deviceId); - - return S_OK; - } - - HRESULT WindowsAudioDeviceManager::OnDeviceRemoved(LPCWSTR deviceId) - { - RTC_LOG(LS_INFO) << "MMF: Device removed: " << deviceId; - - removeDevice(deviceId); - - return S_OK; - } - - HRESULT WindowsAudioDeviceManager::OnDeviceStateChanged(LPCWSTR deviceId, DWORD newState) - { - RTC_LOG(LS_INFO) << "MMF: Device state changed: " << deviceId; - - if (deviceId == nullptr) { - return S_OK; - } - - switch (newState) { - case DEVICE_STATE_ACTIVE: - addDevice(deviceId); - break; - - case DEVICE_STATE_DISABLED: - case DEVICE_STATE_NOTPRESENT: - case DEVICE_STATE_UNPLUGGED: - removeDevice(deviceId); - break; - } - - return S_OK; - } - - HRESULT WindowsAudioDeviceManager::OnPropertyValueChanged(LPCWSTR /*deviceId*/, const PROPERTYKEY /*key*/) - { - return S_OK; - } - - DeviceFormFactor WindowsAudioDeviceManager::getActualFormFactor(EndpointFormFactor formFactor) { - switch (formFactor) { - case RemoteNetworkDevice: - case UnknownDigitalPassthrough: - case EndpointFormFactor_enum_count: - case UnknownFormFactor: - case LineLevel: - case SPDIF: - return DeviceFormFactor::ffUnknown; - case Speakers: - return DeviceFormFactor::ffSpeaker; - case Headphones: - return DeviceFormFactor::ffHeadphone; - case Headset: - case Handset: - return DeviceFormFactor::ffHeadset; - case Microphone: - return DeviceFormFactor::ffMicrophone; - case DigitalAudioDisplayDevice: // for audio devices this means hdmi - return DeviceFormFactor::ffUnknown; - default: - return DeviceFormFactor::ffUnknown; - } - } - - DeviceTransport WindowsAudioDeviceManager::getActualTransport(EndpointFormFactor formFactor) { - // for Windows, only HDMI can be reliably determined - switch (formFactor) { - case DigitalAudioDisplayDevice: - return DeviceTransport::trHdmi; - default: - return DeviceTransport::trUnknown; - } - } - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/video/CustomVideoSource.cpp b/webrtc-jni/src/main/cpp/src/media/video/CustomVideoSource.cpp deleted file mode 100644 index db1f979..0000000 --- a/webrtc-jni/src/main/cpp/src/media/video/CustomVideoSource.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/video/CustomVideoSource.h" - -namespace jni -{ - CustomVideoSource::CustomVideoSource(std::shared_ptr clock) : - clock_(clock), - frame_id_(0) - { - } - - bool CustomVideoSource::is_screencast() const - { - return false; - } - - std::optional CustomVideoSource::needs_denoising() const - { - return false; - } - - webrtc::MediaSourceInterface::SourceState CustomVideoSource::state() const - { - return kLive; - } - - bool CustomVideoSource::remote() const - { - return false; - } - - void CustomVideoSource::PushFrame(const webrtc::VideoFrame& frame) - { - // Create frame with proper timestamp - webrtc::VideoFrame timestamped_frame = frame; - - // Use synchronized clock for timestamp - int64_t timestamp_us = clock_->GetTimestampUs(); - timestamped_frame.set_timestamp_us(timestamp_us); - - // Set RTP timestamp (90kHz clock) - uint32_t rtp_timestamp = static_cast((timestamp_us * 90) / 1000); - timestamped_frame.set_rtp_timestamp(rtp_timestamp); - - // Set NTP time for synchronization - timestamped_frame.set_ntp_time_ms(clock_->GetNtpTime().ToMs()); - - // Increment frame ID - timestamped_frame.set_id(frame_id_++); - - OnFrame(timestamped_frame); - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/video/RawVideoFileSink.cpp b/webrtc-jni/src/main/cpp/src/media/video/RawVideoFileSink.cpp deleted file mode 100644 index def7961..0000000 --- a/webrtc-jni/src/main/cpp/src/media/video/RawVideoFileSink.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/video/RawVideoFileSink.h" - -#include "rtc_base/logging.h" - -namespace jni -{ - RawVideoFileSink::RawVideoFileSink(std::string fileName) - { - outputStream.open(fileName, std::ofstream::out | std::ofstream::binary | std::ofstream::trunc); - } - - RawVideoFileSink::~RawVideoFileSink() - { - outputStream.flush(); - outputStream.close(); - } - - void RawVideoFileSink::OnFrame(const webrtc::VideoFrame & frame) - { - RTC_LOG(LS_INFO) << "VideoFrame: " << frame.width() << "x" << frame.height() << " timestamp: " << frame.timestamp_us(); - - //frame.video_frame_buffer()->ToI420(); - } - - void RawVideoFileSink::OnDiscardedFrame() - { - RTC_LOG(LS_INFO) << __FUNCTION__; - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/video/VideoCapture.cpp b/webrtc-jni/src/main/cpp/src/media/video/VideoCapture.cpp deleted file mode 100644 index 851209e..0000000 --- a/webrtc-jni/src/main/cpp/src/media/video/VideoCapture.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/video/VideoCapture.h" -#include "Exception.h" - -#include "rtc_base/logging.h" -#include "modules/video_capture/video_capture_factory.h" - -namespace jni -{ - VideoCapture::VideoCapture() : VideoCaptureBase(), - captureModule(nullptr) - { - } - - VideoCapture::~VideoCapture() - { - destroy(); - } - - void VideoCapture::start() - { - if (!device) { - throw new Exception("Video device must be set"); - } - - std::unique_ptr info(webrtc::VideoCaptureFactory::CreateDeviceInfo()); - - if (!info) { - throw new Exception("Create video DeviceInfo failed"); - } - - uint32_t num = info->NumberOfDevices(); - - if (num < 1) { - throw new Exception("No video capture devices available"); - } - - std::string devUid; - const uint32_t size = webrtc::kVideoCaptureDeviceNameLength; - - for (uint32_t i = 0; i < num; ++i) { - char name[size] = { 0 }; - char guid[size] = { 0 }; - - int32_t ret = info->GetDeviceName(i, name, size, guid, size); - - if (ret != 0) { - RTC_LOG(LS_WARNING) << "Get video capture device name failed"; - continue; - } - - if (device->getName().compare(name) == 0) { - devUid = guid; - break; - } - } - - if (devUid.empty()) { - throw new Exception("Device %s not found", device->getName().c_str()); - } - - captureModule = webrtc::VideoCaptureFactory::Create(devUid.c_str()); - - if (!captureModule) { - throw new Exception("Create VideoCaptureModule for UID %s failed", devUid.c_str()); - } - - captureModule->RegisterCaptureDataCallback(std::move(sink).release()); - - capability.videoType = webrtc::VideoType::kI420; - - if (captureModule->StartCapture(capability) != 0) { - destroy(); - - throw new Exception("Start video capture for UID %s failed", devUid.c_str()); - } - - if (!captureModule || !captureModule->CaptureStarted()) { - throw new Exception("Start video capture failed"); - } - } - - void VideoCapture::stop() - { - destroy(); - } - - void VideoCapture::destroy() - { - if (!captureModule) { - return; - } - if (captureModule->CaptureStarted()) { - captureModule->StopCapture(); - } - - captureModule->DeRegisterCaptureDataCallback(); - captureModule = nullptr; - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/video/VideoCaptureBase.cpp b/webrtc-jni/src/main/cpp/src/media/video/VideoCaptureBase.cpp deleted file mode 100644 index 57d32a1..0000000 --- a/webrtc-jni/src/main/cpp/src/media/video/VideoCaptureBase.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/video/VideoCaptureBase.h" - -namespace jni -{ - VideoCaptureBase::VideoCaptureBase() - { - capability.width = static_cast(1280); - capability.height = static_cast(720); - capability.maxFPS = static_cast(30); - } - - VideoCaptureBase::~VideoCaptureBase() - { - } - - void VideoCaptureBase::setDevice(const avdev::DevicePtr & device) - { - this->device = device; - } - - void VideoCaptureBase::setVideoCaptureCapability(const webrtc::VideoCaptureCapability & capability) - { - this->capability = capability; - } - - void VideoCaptureBase::setVideoSink(std::unique_ptr> sink) - { - this->sink = std::move(sink); - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/video/VideoCaptureCapability.cpp b/webrtc-jni/src/main/cpp/src/media/video/VideoCaptureCapability.cpp deleted file mode 100644 index b08845b..0000000 --- a/webrtc-jni/src/main/cpp/src/media/video/VideoCaptureCapability.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/video/VideoCaptureCapability.h" -#include "JavaClasses.h" -#include "JNI_WebRTC.h" - -namespace jni -{ - namespace avdev - { - bool VideoCaptureCapability::operator<(const VideoCaptureCapability & other) const - { - if (width > other.width) { - return true; - } - if (height > other.height) { - return true; - } - if (maxFPS > other.maxFPS) { - return true; - } - if (videoType > other.videoType) { - return true; - } - return false; - } - } - - namespace VideoCaptureCapability - { - JavaLocalRef toJava(JNIEnv * env, const avdev::VideoCaptureCapability & capability) - { - const auto javaClass = JavaClasses::get(env); - - jobject obj = env->NewObject(javaClass->cls, javaClass->ctor, - static_cast(capability.width), - static_cast(capability.height), - static_cast(capability.maxFPS)); - - return JavaLocalRef(env, obj); - } - - JavaVideoCaptureCapabilityClass::JavaVideoCaptureCapabilityClass(JNIEnv * env) - { - cls = FindClass(env, PKG_VIDEO"VideoCaptureCapability"); - - ctor = GetMethod(env, cls, "", "(III)V"); - } - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/video/VideoDevice.cpp b/webrtc-jni/src/main/cpp/src/media/video/VideoDevice.cpp deleted file mode 100644 index 67d5c82..0000000 --- a/webrtc-jni/src/main/cpp/src/media/video/VideoDevice.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/video/VideoDevice.h" -#include "JavaClasses.h" -#include "JavaString.h" -#include "JavaObject.h" -#include "JNI_WebRTC.h" - -namespace jni -{ - namespace avdev - { - VideoDevice::VideoDevice(std::string name, std::string descriptor) : - Device(name, descriptor) - { - } - } - - namespace VideoDevice - { - JavaLocalRef toJavaVideoDevice(JNIEnv * env, const avdev::VideoDevice & device) - { - const auto javaClass = JavaClasses::get(env); - - jobject obj = env->NewObject(javaClass->cls, javaClass->ctor, - JavaString::toJava(env, device.getName()).get(), - JavaString::toJava(env, device.getDescriptor()).get()); - - return JavaLocalRef(env, obj); - } - - avdev::VideoDevice toNativeVideoDevice(JNIEnv * env, const JavaRef & javaType) - { - const auto javaClass = JavaClasses::get(env); - - JavaObject obj(env, javaType); - - return avdev::VideoDevice( - JavaString::toNative(env, obj.getString(javaClass->name)), - JavaString::toNative(env, obj.getString(javaClass->descriptor)) - ); - } - - JavaVideoDeviceClass::JavaVideoDeviceClass(JNIEnv * env) - { - cls = FindClass(env, PKG_VIDEO"VideoDevice"); - - ctor = GetMethod(env, cls, "", "(" STRING_SIG STRING_SIG ")V"); - - name = GetFieldID(env, cls, "name", STRING_SIG); - descriptor = GetFieldID(env, cls, "descriptor", STRING_SIG); - } - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/video/VideoDeviceManager.cpp b/webrtc-jni/src/main/cpp/src/media/video/VideoDeviceManager.cpp deleted file mode 100644 index ec05014..0000000 --- a/webrtc-jni/src/main/cpp/src/media/video/VideoDeviceManager.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/video/VideoDeviceManager.h" - -namespace jni -{ - namespace avdev - { - VideoDeviceManager::VideoDeviceManager() - { - } - - VideoDevicePtr VideoDeviceManager::getDefaultVideoCaptureDevice() - { - if (getDefaultCaptureDevice() == nullptr && captureDevices.empty()) { - getVideoCaptureDevices(); - } - - if (getDefaultCaptureDevice() == nullptr && !captureDevices.empty()) { - setDefaultCaptureDevice(*captureDevices.devices().begin()); - } - - return getDefaultCaptureDevice(); - } - - void VideoDeviceManager::setDefaultCaptureDevice(VideoDevicePtr device) - { - std::unique_lock mlock(mutex); - - defaultCaptureDevice = device; - } - - VideoDevicePtr VideoDeviceManager::getDefaultCaptureDevice() - { - std::unique_lock mlock(mutex); - - return defaultCaptureDevice; - } - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/video/VideoTrackDesktopSource.cpp b/webrtc-jni/src/main/cpp/src/media/video/VideoTrackDesktopSource.cpp deleted file mode 100644 index 6192d6d..0000000 --- a/webrtc-jni/src/main/cpp/src/media/video/VideoTrackDesktopSource.cpp +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/video/VideoTrackDesktopSource.h" -#include "Exception.h" - -#include "api/video/i420_buffer.h" -#include "libyuv/convert.h" -#include "modules/desktop_capture/cropping_window_capturer.h" -#include "modules/desktop_capture/desktop_capture_options.h" -#include "modules/video_capture/video_capture_factory.h" -#include "third_party/libyuv/include/libyuv/video_common.h" -#include "rtc_base/logging.h" -#include "rtc_base/thread.h" - -#include "modules/desktop_capture/desktop_capturer.h" -#include "modules/desktop_capture/desktop_and_cursor_composer.h" -#include "modules/desktop_capture/mouse_cursor_monitor.h" - -namespace jni -{ - VideoTrackDesktopSource::VideoTrackDesktopSource() : - AdaptedVideoTrackSource(), - frameRate(20), - isCapturing(false), - focusSelectedSource(true), - sourceState(kInitializing), - sourceId(-1), - sourceIsWindow(false) - { - } - - VideoTrackDesktopSource::~VideoTrackDesktopSource() - { - stop(); - } - - void VideoTrackDesktopSource::setSourceId(webrtc::DesktopCapturer::SourceId source, bool isWindow) - { - this->sourceId = source; - this->sourceIsWindow = isWindow; - } - - void VideoTrackDesktopSource::setFrameRate(const uint16_t frameRate) - { - this->frameRate = frameRate; - } - - void VideoTrackDesktopSource::setMaxFrameSize(webrtc::DesktopSize size) - { - this->maxFrameSize = size; - } - - void VideoTrackDesktopSource::setFocusSelectedSource(bool focus) - { - this->focusSelectedSource = focus; - } - - void VideoTrackDesktopSource::start() - { - if (captureThread.empty()) { - isCapturing = true; - - captureThread = webrtc::PlatformThread::SpawnJoinable( - [&] { - capture(); - }, - "VideoTrackDesktopThread", - webrtc::ThreadAttributes().SetPriority(webrtc::ThreadPriority::kHigh)); - } - } - - void VideoTrackDesktopSource::stop() - { - if (!captureThread.empty()) { - isCapturing = false; - captureThread.Finalize(); - } - } - - void VideoTrackDesktopSource::terminate() - { - // Notify the track that we are permanently done. - sourceState = kEnded; - FireOnChanged(); - } - - bool VideoTrackDesktopSource::is_screencast() const - { - return true; - } - - std::optional VideoTrackDesktopSource::needs_denoising() const - { - return false; - } - - webrtc::MediaSourceInterface::SourceState VideoTrackDesktopSource::state() const - { - return sourceState; - } - - bool VideoTrackDesktopSource::remote() const - { - return false; - } - - void VideoTrackDesktopSource::OnCaptureResult(webrtc::DesktopCapturer::Result result, std::unique_ptr frame) - { - if (result != webrtc::DesktopCapturer::Result::SUCCESS) { - if (result == webrtc::DesktopCapturer::Result::ERROR_PERMANENT) { - RTC_LOG(LS_ERROR) << "Permanent error capturing desktop frame. Stopping track."; - - isCapturing = false; - } - - return; - } - - int width = frame->size().width(); - int height = frame->size().height(); - - if (width == 1 && height == 1) { - // Window has been minimized (hidden). - if (lastFrame != nullptr) { - process(lastFrame); - } - } - else { - // Copy current frame as backup, in order to show it when the window is minimized. - lastFrame.reset(new webrtc::BasicDesktopFrame(webrtc::DesktopSize(width, height))); - lastFrame->CopyPixelsFrom(frame->data(), frame->stride(), webrtc::DesktopRect::MakeWH(width, height)); - - process(frame); - } - } - - void VideoTrackDesktopSource::process(std::unique_ptr& frame) - { - int64_t time = webrtc::TimeMicros(); - - int width = frame->size().width(); - int height = frame->size().height(); - - int adapted_width; - int adapted_height; - - int crop_x = 0; - int crop_y = 0; - int crop_w = width; - int crop_h = height; - - if (!AdaptFrame(width, height, time, &adapted_width, &adapted_height, &crop_w, &crop_h, &crop_x, &crop_y)) { - // Drop frame in order to respect frame rate constraint. - return; - } - -#if defined(WEBRTC_WIN) - // Crop black window borders. - bool fullscreen = frame->stride() == (frame->size().width() * webrtc::DesktopFrame::kBytesPerPixel); - - if (!fullscreen) { - const webrtc::DesktopVector& top_left = frame->top_left(); - const int32_t border = GetSystemMetrics(SM_CXPADDEDBORDER); - - crop_x = border; - crop_y = top_left.y() < 0 ? -top_left.y() : 0; - crop_w = width - crop_x * 2; - crop_h = height - (crop_y + border); - } -#endif - - if (!buffer || buffer->width() != crop_w || buffer->height() != crop_h) { - buffer = webrtc::I420Buffer::Create(crop_w, crop_h); - } - - const int conversionResult = libyuv::ConvertToI420( - frame->data(), - 0, - buffer->MutableDataY(), buffer->StrideY(), - buffer->MutableDataU(), buffer->StrideU(), - buffer->MutableDataV(), buffer->StrideV(), - crop_x, crop_y, - frame->stride() / webrtc::DesktopFrame::kBytesPerPixel, buffer->height(), crop_w, crop_h, - libyuv::kRotate0, - libyuv::FOURCC_ARGB); - - if (conversionResult >= 0) { - if (!maxFrameSize.is_empty()) { - // Adapt frame size to contraints. - int max_width = maxFrameSize.width(); - int max_height = maxFrameSize.height(); - - if (adapted_width > max_width) { - double scale = max_width / (double)adapted_width; - adapted_width = max_width; - adapted_height = (int)(adapted_height * scale); - } - else if (adapted_height > max_height) { - double scale = max_height / (double)adapted_height; - adapted_width = (int)(adapted_width * scale); - adapted_height = max_height; - } - } - - if (adapted_width != width || adapted_height != height) { - // Video adapter has requested a down-scale. Allocate a new buffer and return scaled version. - webrtc::scoped_refptr scaled_buffer = webrtc::I420Buffer::Create(adapted_width, adapted_height); - - scaled_buffer->ScaleFrom(*buffer); - - OnFrame(webrtc::VideoFrame::Builder() - .set_video_frame_buffer(scaled_buffer) - .set_rotation(webrtc::kVideoRotation_0) - .set_timestamp_us(time) - .build()); - } - else { - // No adaptations needed, just return the frame as is. - OnFrame(webrtc::VideoFrame::Builder() - .set_video_frame_buffer(buffer) - .set_rotation(webrtc::kVideoRotation_0) - .set_timestamp_us(time) - .build()); - } - } - } - - void VideoTrackDesktopSource::capture() - { - auto options = webrtc::DesktopCaptureOptions::CreateDefault(); - // Enable desktop effects. - options.set_disable_effects(false); - -#if defined(WEBRTC_MAC) - options.set_allow_iosurface(true); -#endif -#if defined(WEBRTC_WIN) - options.set_allow_directx_capturer(true); -#endif - - std::unique_ptr capturer; - - if (sourceIsWindow) { - capturer.reset(new webrtc::DesktopAndCursorComposer( - webrtc::DesktopCapturer::CreateWindowCapturer(options), - options)); - } - else { - capturer.reset(new webrtc::DesktopAndCursorComposer( - webrtc::DesktopCapturer::CreateScreenCapturer(options), - options)); - } - - if (!capturer->SelectSource(sourceId)) { - terminate(); - return; - } - - capturer->Start(this); - - if (focusSelectedSource) { - capturer->FocusOnSelectedSource(); - } - - sourceState = kLive; - - int msPerFrame = 1000 / frameRate; - - while (isCapturing) { -#if defined(WEBRTC_MAC) - CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true); -#endif - capturer->CaptureFrame(); - - webrtc::Thread::SleepMs(msPerFrame); - } - - capturer.reset(); - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/video/VideoTrackDeviceSource.cpp b/webrtc-jni/src/main/cpp/src/media/video/VideoTrackDeviceSource.cpp deleted file mode 100644 index 555023d..0000000 --- a/webrtc-jni/src/main/cpp/src/media/video/VideoTrackDeviceSource.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/video/VideoTrackDeviceSource.h" -#include "Exception.h" - -#include "api/video/i420_buffer.h" -#include "modules/video_capture/video_capture_factory.h" - -namespace jni -{ - VideoTrackDeviceSource::VideoTrackDeviceSource() : - VideoTrackSource(/*remote=*/false), - VideoTrackDeviceSourceBase(), - captureModule(nullptr) - { - } - - VideoTrackDeviceSource::~VideoTrackDeviceSource() - { - destroy(); - } - - void VideoTrackDeviceSource::start() - { - std::unique_ptr info(webrtc::VideoCaptureFactory::CreateDeviceInfo()); - - if (!info) { - throw new Exception("Create video DeviceInfo failed"); - } - - uint32_t num = info->NumberOfDevices(); - - if (num < 1) { - throw new Exception("No video capture devices available"); - } - - if (device) { - std::string devUid; - const uint32_t size = webrtc::kVideoCaptureDeviceNameLength; - - for (uint32_t i = 0; i < num; ++i) { - char name[size] = { 0 }; - char guid[size] = { 0 }; - - int32_t ret = info->GetDeviceName(i, name, size, guid, size); - - if (ret != 0) { - RTC_LOG(LS_WARNING) << "Get video capture device name failed"; - continue; - } - - if (device->getName().compare(name) == 0) { - devUid = guid; - break; - } - } - - if (devUid.empty()) { - throw new Exception("Device %s not found", device->getName().c_str()); - } - - captureModule = webrtc::VideoCaptureFactory::Create(devUid.c_str()); - - if (!captureModule) { - throw new Exception("Create VideoCaptureModule for UID %s failed", devUid.c_str()); - } - - if (!startCapture()) { - destroy(); - - throw new Exception("Start video capture for UID %s failed", devUid.c_str()); - } - } - - if (!captureModule) { - // No user-defined capture device. Select first available device. - const uint32_t size = webrtc::kVideoCaptureDeviceNameLength; - - for (uint32_t i = 0; i < num; ++i) { - char name[size] = { 0 }; - char guid[size] = { 0 }; - - int32_t ret = info->GetDeviceName(i, name, size, guid, size); - - if (ret != 0) { - RTC_LOG(LS_WARNING) << "Get video capture device name failed"; - continue; - } - - captureModule = webrtc::VideoCaptureFactory::Create(guid); - - if (!captureModule) { - continue; - } - - if (startCapture()) { - break; - } - else { - // Clean up resources. Try next device. - destroy(); - } - } - } - - if (!captureModule || !captureModule->CaptureStarted()) { - throw new Exception("Start video capture failed"); - } - } - - void VideoTrackDeviceSource::stop() - { - destroy(); - } - - void VideoTrackDeviceSource::destroy() - { - if (!captureModule) { - return; - } - if (captureModule->CaptureStarted()) { - captureModule->StopCapture(); - } - - captureModule->DeRegisterCaptureDataCallback(); - captureModule = nullptr; - } - - void VideoTrackDeviceSource::AddOrUpdateSink(webrtc::VideoSinkInterface * sink, const webrtc::VideoSinkWants & wants) - { - broadcaster.AddOrUpdateSink(sink, wants); - - updateVideoAdapter(); - } - - void VideoTrackDeviceSource::RemoveSink(webrtc::VideoSinkInterface * sink) - { - broadcaster.RemoveSink(sink); - - updateVideoAdapter(); - } - - bool VideoTrackDeviceSource::startCapture() - { - captureModule->RegisterCaptureDataCallback(this); - - capability.videoType = webrtc::VideoType::kI420; - - return captureModule->StartCapture(capability) == 0; - } - - void VideoTrackDeviceSource::updateVideoAdapter() - { - webrtc::VideoSinkWants wants = broadcaster.wants(); - - videoAdapter.OnOutputFormatRequest(std::make_pair(capability.width, capability.height), wants.max_pixel_count, wants.max_framerate_fps); - } - - void VideoTrackDeviceSource::OnFrame(const webrtc::VideoFrame & frame) - { - int croppedWidth = 0; - int croppedHeight = 0; - int outWidth = 0; - int outHeight = 0; - - if (!videoAdapter.AdaptFrameResolution(frame.width(), frame.height(), frame.timestamp_us() * 1000, - &croppedWidth, &croppedHeight, &outWidth, &outHeight)) { - // Drop frame in order to respect frame rate constraint. - return; - } - - if (outHeight != frame.height() || outWidth != frame.width()) { - // Video adapter has requested a down-scale. Allocate a new buffer and return scaled version. - webrtc::scoped_refptr scaled_buffer = webrtc::I420Buffer::Create(outWidth, outHeight); - - scaled_buffer->ScaleFrom(*frame.video_frame_buffer()->ToI420()); - - broadcaster.OnFrame(webrtc::VideoFrame::Builder() - .set_video_frame_buffer(scaled_buffer) - .set_rotation(webrtc::kVideoRotation_0) - .set_timestamp_us(frame.timestamp_us()) - .set_id(frame.id()) - .build()); - } - else { - // No adaptations needed, just return the frame as is. - broadcaster.OnFrame(frame); - } - } - - webrtc::VideoSourceInterface * VideoTrackDeviceSource::source() - { - return this; - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/video/VideoTrackDeviceSourceBase.cpp b/webrtc-jni/src/main/cpp/src/media/video/VideoTrackDeviceSourceBase.cpp deleted file mode 100644 index aedceb2..0000000 --- a/webrtc-jni/src/main/cpp/src/media/video/VideoTrackDeviceSourceBase.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/video/VideoTrackDeviceSourceBase.h" - -namespace jni -{ - VideoTrackDeviceSourceBase::VideoTrackDeviceSourceBase() - { - capability.width = static_cast(1280); - capability.height = static_cast(720); - capability.maxFPS = static_cast(30); - } - - VideoTrackDeviceSourceBase::~VideoTrackDeviceSourceBase() - { - } - - void VideoTrackDeviceSourceBase::setVideoDevice(const avdev::VideoDevicePtr & device) - { - this->device = device; - } - - void VideoTrackDeviceSourceBase::setVideoCaptureCapability(const webrtc::VideoCaptureCapability & capability) - { - this->capability = capability; - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/video/desktop/DesktopCaptureCallback.cpp b/webrtc-jni/src/main/cpp/src/media/video/desktop/DesktopCaptureCallback.cpp deleted file mode 100644 index 46b8d6d..0000000 --- a/webrtc-jni/src/main/cpp/src/media/video/desktop/DesktopCaptureCallback.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/video/desktop/DesktopCaptureCallback.h" -#include "media/video/desktop/DesktopFrame.h" -#include "JavaClasses.h" -#include "JavaEnums.h" -#include "JNI_WebRTC.h" - -#include "libyuv/convert.h" -#include "libyuv/video_common.h" -#include "modules/desktop_capture/desktop_frame.h" -#include "rtc_base/logging.h" -#include "rtc_base/time_utils.h" - -#if defined(WEBRTC_WIN) -#include "rtc_base/win32.h" -#endif - -namespace jni -{ - DesktopCaptureCallback::DesktopCaptureCallback(JNIEnv * env, const JavaGlobalRef & callback) : - callback(callback), - javaClass(JavaClasses::get(env)), - javaFrameClass(JavaClasses::get(env)) - { - } - - void DesktopCaptureCallback::OnCaptureResult(webrtc::DesktopCapturer::Result result, std::unique_ptr frame) - { - JNIEnv * env = AttachCurrentThread(); - - if (result != webrtc::DesktopCapturer::Result::SUCCESS) { - return; - } - - auto jresult = JavaEnums::toJava(env, result); - - int width = frame->size().width(); - int height = frame->size().height(); - - int crop_x = 0; - int crop_y = 0; - int crop_w = width; - int crop_h = height; - -#if defined(WEBRTC_WIN) - // Crop black window borders. - bool fullscreen = frame->stride() == (frame->size().width() * webrtc::DesktopFrame::kBytesPerPixel); - - if (!fullscreen) { - const webrtc::DesktopVector & top_left = frame->top_left(); - const int32_t border = GetSystemMetrics(SM_CXPADDEDBORDER); - - crop_x = border; - crop_y = top_left.y() < 0 ? -top_left.y() : 0; - crop_w = width - crop_x * 2; - crop_h = height - (crop_y + border); - } -#endif - - if (!i420Buffer || i420Buffer->width() != crop_w || i420Buffer->height() != crop_h) { - i420Buffer = webrtc::I420Buffer::Create(crop_w, crop_h); - } - - const int conversionResult = libyuv::ConvertToI420( - frame->data(), - 0, - i420Buffer->MutableDataY(), i420Buffer->StrideY(), - i420Buffer->MutableDataU(), i420Buffer->StrideU(), - i420Buffer->MutableDataV(), i420Buffer->StrideV(), - crop_x, crop_y, - frame->stride() / webrtc::DesktopFrame::kBytesPerPixel, i420Buffer->height(), crop_w, crop_h, - libyuv::kRotate0, - libyuv::FOURCC_ARGB); - - if (conversionResult < 0) { - RTC_LOG(LS_ERROR) << "Failed to convert desktop frame to I420"; - return; - } - - jint rotation = static_cast(webrtc::kVideoRotation_0); - jlong timestamp = webrtc::TimeMicros() * webrtc::kNumNanosecsPerMicrosec; - - webrtc::scoped_refptr i420BufferCopy = webrtc::I420Buffer::Copy(*i420Buffer); - i420BufferCopy->AddRef(); - - JavaLocalRef jBuffer = I420Buffer::toJava(env, i420BufferCopy); - jobject jFrame = env->NewObject(javaFrameClass->cls, javaFrameClass->ctor, jBuffer.get(), rotation, timestamp); - - env->CallVoidMethod(callback, javaClass->onCaptureResult, jresult.get(), jFrame); - - ExceptionCheck(env); - env->DeleteLocalRef(jBuffer); - env->DeleteLocalRef(jFrame); - } - - DesktopCaptureCallback::JavaDesktopCaptureCallbackClass::JavaDesktopCaptureCallbackClass(JNIEnv * env) - { - jclass cls = FindClass(env, PKG_DESKTOP"DesktopCaptureCallback"); - - onCaptureResult = GetMethod(env, cls, "onCaptureResult", "(L" PKG_DESKTOP "DesktopCapturer$Result;L" PKG_VIDEO "VideoFrame;)V"); - } -} diff --git a/webrtc-jni/src/main/cpp/src/media/video/desktop/DesktopCapturer.cpp b/webrtc-jni/src/main/cpp/src/media/video/desktop/DesktopCapturer.cpp deleted file mode 100644 index 6df76c9..0000000 --- a/webrtc-jni/src/main/cpp/src/media/video/desktop/DesktopCapturer.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/video/desktop/DesktopCapturer.h" - -#include "modules/desktop_capture/desktop_capturer.h" -#include "modules/desktop_capture/desktop_capture_options.h" -#include "modules/desktop_capture/desktop_and_cursor_composer.h" - -namespace jni -{ - DesktopCapturer::DesktopCapturer(bool screenCapturer) : - focusSelectedSource(false) - { - auto options = webrtc::DesktopCaptureOptions::CreateDefault(); - // Enable desktop effects. - options.set_disable_effects(false); - -#if defined(WEBRTC_MAC) - options.set_allow_iosurface(true); -#endif -#if defined(WEBRTC_WIN) - options.set_allow_directx_capturer(true); -#endif - - if (screenCapturer) { - capturer = std::make_unique( - webrtc::DesktopCapturer::CreateScreenCapturer(options), options); - } - else { - capturer = std::make_unique( - webrtc::DesktopCapturer::CreateWindowCapturer(options), options); - } - } - - DesktopCapturer::~DesktopCapturer() - { - capturer.reset(); - } - - void DesktopCapturer::Start(webrtc::DesktopCapturer::Callback * callback) - { - capturer->Start(callback); - - if (focusSelectedSource) { - capturer->FocusOnSelectedSource(); - } - } - - void DesktopCapturer::SetMaxFrameRate(uint32_t max_frame_rate) - { - capturer->SetMaxFrameRate(max_frame_rate); - } - - void DesktopCapturer::SetSharedMemoryFactory(std::unique_ptr factory) - { - capturer->SetSharedMemoryFactory(std::move(factory)); - } - - void DesktopCapturer::CaptureFrame() - { -#if defined(WEBRTC_MAC) - CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true); -#endif - - capturer->CaptureFrame(); - } - - void DesktopCapturer::SetExcludedWindow(webrtc::WindowId window) - { - capturer->SetExcludedWindow(window); - } - - bool DesktopCapturer::GetSourceList(webrtc::DesktopCapturer::SourceList * sources) - { - return capturer->GetSourceList(sources); - } - - bool DesktopCapturer::SelectSource(webrtc::DesktopCapturer::SourceId id) - { - return capturer->SelectSource(id); - } - - bool DesktopCapturer::FocusOnSelectedSource() - { - return capturer->FocusOnSelectedSource(); - } - - void DesktopCapturer::setFocusSelectedSource(bool focus) - { - this->focusSelectedSource = focus; - } - - bool DesktopCapturer::IsOccluded(const webrtc::DesktopVector & pos) - { - return capturer->IsOccluded(pos); - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/video/desktop/DesktopFrame.cpp b/webrtc-jni/src/main/cpp/src/media/video/desktop/DesktopFrame.cpp deleted file mode 100644 index d621241..0000000 --- a/webrtc-jni/src/main/cpp/src/media/video/desktop/DesktopFrame.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/video/desktop/DesktopFrame.h" -#include "JavaClasses.h" -#include "JavaDimension.h" -#include "JavaRectangle.h" -#include "JNI_WebRTC.h" - -namespace jni -{ - namespace DesktopFrame - { - JavaLocalRef toJava(JNIEnv * env, const webrtc::DesktopFrame * frame) - { - if (frame == nullptr) { - return nullptr; - } - - const webrtc::DesktopRect & rect = frame->rect(); - const webrtc::DesktopSize & size = frame->size(); - - const auto javaClass = JavaClasses::get(env); - - jobject buffer = env->NewDirectByteBuffer(frame->data(), frame->stride() * frame->size().height()); - - jobject object = env->NewObject(javaClass->cls, javaClass->ctor, - JavaRectangle::toJava(env, rect.left(), rect.top(), rect.width(), rect.height()).get(), - JavaDimension::toJava(env, size.width(), size.height()).get(), - static_cast(frame->scale_factor()), - static_cast(frame->stride()), - buffer); - - return JavaLocalRef(env, object); - } - - JavaDesktopFrameClass::JavaDesktopFrameClass(JNIEnv * env) - { - cls = FindClass(env, PKG_DESKTOP"DesktopFrame"); - - ctor = GetMethod(env, cls, "", "(Ljava/awt/Rectangle;Ljava/awt/Dimension;FI" BYTE_BUFFER_SIG ")V"); - } - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/video/desktop/DesktopSource.cpp b/webrtc-jni/src/main/cpp/src/media/video/desktop/DesktopSource.cpp deleted file mode 100644 index bac8b6e..0000000 --- a/webrtc-jni/src/main/cpp/src/media/video/desktop/DesktopSource.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/video/desktop/DesktopSource.h" -#include "JavaClasses.h" -#include "JavaObject.h" -#include "JavaString.h" -#include "JNI_WebRTC.h" - -namespace jni -{ - namespace DesktopSource - { - JavaLocalRef toJava(JNIEnv * env, const webrtc::DesktopCapturer::Source & source) - { - const std::shared_ptr javaClass = JavaClasses::get(env); - - jobject obj = env->NewObject(javaClass->cls, javaClass->ctor, - JavaString::toJava(env, source.title).get(), - static_cast(source.id)); - - return JavaLocalRef(env, obj); - } - - webrtc::DesktopCapturer::Source toNative(JNIEnv * env, const JavaRef & javaType) - { - const std::shared_ptr javaClass = JavaClasses::get(env); - - JavaObject obj(env, javaType); - - auto source = webrtc::DesktopCapturer::Source(); - source.id = static_cast(obj.getLong(javaClass->id)); - source.title = JavaString::toNative(env, obj.getString(javaClass->title)); - - return source; - } - - JavaDesktopSourceClass::JavaDesktopSourceClass(JNIEnv * env) - { - cls = FindClass(env, PKG_DESKTOP"DesktopSource"); - - ctor = GetMethod(env, cls, "", "(" STRING_SIG "J)V"); - - id = GetFieldID(env, cls, "id", "J"); - title = GetFieldID(env, cls, "title", STRING_SIG); - } - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/video/desktop/linux/LinuxPowerManagement.cpp b/webrtc-jni/src/main/cpp/src/media/video/desktop/linux/LinuxPowerManagement.cpp deleted file mode 100644 index 05611a8..0000000 --- a/webrtc-jni/src/main/cpp/src/media/video/desktop/linux/LinuxPowerManagement.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/video/desktop/linux/LinuxPowerManagement.h" - -#include -#include - -#include "rtc_base/logging.h" - -namespace jni -{ - namespace avdev - { - LinuxPowerManagement::LinuxPowerManagement() - { - } - - void LinuxPowerManagement::enableUserActivity() - { - DBusError error; - dbus_error_init(&error); - - DBusConnection * dbusConnection = dbus_bus_get(DBUS_BUS_SESSION, &error); - - if (dbus_error_is_set(&error)) { - // throw - RTC_LOG(LS_ERROR) << "[PowerManagement] Cannot connect to session bus: " << error.message; - dbus_error_free(&error); - return; - } - - if (dbus_bus_name_has_owner(dbusConnection, BUS_SERVICE_NAME, NULL)) { - RTC_LOG(LS_INFO) << "[PowerManagement] Found service: " << BUS_SERVICE_NAME; - } - else { - // throw - RTC_LOG(LS_WARNING) << "[PowerManagement] Cannot find service: " << BUS_SERVICE_NAME; - return; - } - - DBusMessage * message = dbus_message_new_method_call(BUS_SERVICE_NAME, BUS_SERVICE_PATH, BUS_INTERFACE, - "Inhibit"); - - if (message == nullptr) { - // throw - return; - } - - dbus_message_append_args(message, DBUS_TYPE_STRING, &appName, DBUS_TYPE_STRING, &reason, DBUS_TYPE_INVALID); - - DBusMessage * reply = dbus_connection_send_with_reply_and_block(dbusConnection, message, 50, &error); - dbus_message_unref(message); - - if (dbus_error_is_set(&error)) { - dbus_error_free(&error); - dbus_connection_unref(dbusConnection); - // throw - RTC_LOG(LS_ERROR) << "[PowerManagement] Cannot retrieve cookie"; - return; - } - - DBusMessageIter reply_iter; - dbus_message_iter_init(reply, &reply_iter); - dbus_message_iter_get_basic(&reply_iter, &dbusCookie); - - RTC_LOG(LS_INFO) << "[PowerManagement] Acquired screensaver inhibition cookie"; - - dbus_message_unref(reply); - dbus_connection_unref(dbusConnection); - } - - void LinuxPowerManagement::disableUserActivity() - { - DBusError error; - dbus_error_init(&error); - - DBusConnection * dbusConnection = dbus_bus_get(DBUS_BUS_SESSION, &error); - - if (dbus_error_is_set(&error)) { - // throw - RTC_LOG(LS_ERROR) << "[PowerManagement] Cannot connect to session bus: " << error.message; - dbus_error_free(&error); - return; - } - - DBusMessage * message = dbus_message_new_method_call(BUS_SERVICE_NAME, BUS_SERVICE_PATH, BUS_INTERFACE, - "UnInhibit"); - - if (message == nullptr) { - // throw - return; - } - - dbus_message_append_args(message, DBUS_TYPE_UINT32, &dbusCookie, DBUS_TYPE_INVALID); - - DBusMessage * reply = dbus_connection_send_with_reply_and_block(dbusConnection, message, 50, &error); - dbus_message_unref(message); - - if (dbus_error_is_set(&error)) { - // throw - RTC_LOG(LS_ERROR) << "[PowerManagement] Cannot release cookie"; - - dbus_error_free(&error); - dbus_connection_unref(dbusConnection); - return; - } - - RTC_LOG(LS_INFO) << "[PowerManagement] Released screensaver inhibition cookie"; - - dbus_message_unref(reply); - dbus_connection_unref(dbusConnection); - } - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/video/desktop/macos/MacOSPowerManagement.cpp b/webrtc-jni/src/main/cpp/src/media/video/desktop/macos/MacOSPowerManagement.cpp deleted file mode 100644 index 426fb93..0000000 --- a/webrtc-jni/src/main/cpp/src/media/video/desktop/macos/MacOSPowerManagement.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/video/desktop/macos/MacOSPowerManagement.h" - -namespace jni -{ - namespace avdev - { - MacOSPowerManagement::MacOSPowerManagement() : - powerAssertion(kIOPMNullAssertionID) - { - } - - void MacOSPowerManagement::enableUserActivity() - { - CFStringRef name = CFSTR("WebRTC-Java processing"); - - if (IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep, kIOPMAssertionLevelOn, name, &powerAssertion) != kIOReturnSuccess) { - powerAssertion = kIOPMNullAssertionID; - } - } - - void MacOSPowerManagement::disableUserActivity() - { - if (powerAssertion != kIOPMNullAssertionID) { - IOPMAssertionRelease(powerAssertion); - powerAssertion = kIOPMNullAssertionID; - } - } - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/video/desktop/windows/WindowsPowerManagement.cpp b/webrtc-jni/src/main/cpp/src/media/video/desktop/windows/WindowsPowerManagement.cpp deleted file mode 100644 index 8ae57ea..0000000 --- a/webrtc-jni/src/main/cpp/src/media/video/desktop/windows/WindowsPowerManagement.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/video/desktop/windows/WindowsPowerManagement.h" - -#include - -namespace jni -{ - namespace avdev - { - WindowsPowerManagement::WindowsPowerManagement() - { - } - - void WindowsPowerManagement::enableUserActivity() - { - SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_AWAYMODE_REQUIRED | ES_DISPLAY_REQUIRED); - } - - void WindowsPowerManagement::disableUserActivity() - { - SetThreadExecutionState(ES_CONTINUOUS); - } - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/video/linux/V4l2VideoDeviceManager.cpp b/webrtc-jni/src/main/cpp/src/media/video/linux/V4l2VideoDeviceManager.cpp deleted file mode 100644 index e7f0e5f..0000000 --- a/webrtc-jni/src/main/cpp/src/media/video/linux/V4l2VideoDeviceManager.cpp +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/video/linux/V4l2VideoDeviceManager.h" -#include "Exception.h" - -#include "rtc_base/logging.h" - -#include -#include -#include -#include -#include - -#define UDEV_SUBSYSTEM "video4linux" -#define UDEV_ADD "add" -#define UDEV_REMOVE "remove" -#define UDEV_CHANGE "change" - -namespace jni -{ - namespace avdev - { - V4l2VideoDeviceManager::V4l2VideoDeviceManager() - { - udev = udev_new(); - - if (!udev) { - throw Exception("V4l2: Create udev failed"); - } - - getVideoCaptureDevices(); - - running = true; - - thread = std::thread(&V4l2VideoDeviceManager::run, this); - } - - V4l2VideoDeviceManager::~V4l2VideoDeviceManager() - { - running = false; - - if (thread.joinable()) { - try { - thread.join(); - } - catch (const std::system_error & error) { - RTC_LOG(LS_ERROR) << "Thread Join Error: " << error.what(); - } - } - - udev_unref(udev); - } - - std::set V4l2VideoDeviceManager::getVideoCaptureDevices() - { - if (!captureDevices.empty()) { - return captureDevices.devices(); - } - - udev_enumerate * enumerate = udev_enumerate_new(udev); - udev_enumerate_add_match_subsystem(enumerate, UDEV_SUBSYSTEM); - udev_enumerate_scan_devices(enumerate); - - udev_list_entry * udev_devices = udev_enumerate_get_list_entry(enumerate); - udev_list_entry * dev_list_entry; - v4l2_capability vcap; - - udev_list_entry_foreach(dev_list_entry, udev_devices) { - const char * path = udev_list_entry_get_name(dev_list_entry); - - if (!path) { - RTC_LOG(LS_ERROR) << "V4l2: Failed to get device sys path"; - continue; - } - - udev_device * dev = udev_device_new_from_syspath(udev, path); - - if (!dev) { - RTC_LOG(LS_ERROR) << "V4l2: Failed to get device from sys path: " << path; - continue; - } - - const char * node = udev_device_get_devnode(dev); - bool error = false; - - int v4l2_fd = open(node, O_RDONLY); - if (v4l2_fd < 0) { - RTC_LOG(LS_ERROR) << "V4l2: Failed to open device: " << node; - error = true; - } - if (ioctlDevice(v4l2_fd, VIDIOC_QUERYCAP, &vcap) == -1) { - RTC_LOG(LS_ERROR) << "V4l2: Failed to query device caps: " << node; - error = true; - } - if (!(vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { - RTC_LOG(LS_ERROR) << "V4l2: Not a video capture device: " << node; - error = true; - } - - v4l2_fmtdesc fmt = { 0 }; - fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - if (ioctlDevice(v4l2_fd, VIDIOC_ENUM_FMT, &fmt) == -1) { - error = true; - } - - close(v4l2_fd); - - if (!error) { - const char * name = (const char *) vcap.card; - - addDevice(name, node); - } - - udev_device_unref(dev); - } - - udev_enumerate_unref(enumerate); - - return captureDevices.devices(); - } - - std::set V4l2VideoDeviceManager::getVideoCaptureCapabilities(const VideoDevice & device) - { - v4l2_capability vcap = { 0 }; - - int v4l2_fd = open(device.getDescriptor().c_str(), O_RDONLY); - if (v4l2_fd < 0) { - throw Exception("V4l2: Failed to open device: %s", device.getName().c_str()); - } - if (ioctlDevice(v4l2_fd, VIDIOC_QUERYCAP, &vcap) == -1) { - throw Exception("V4l2: Failed to query device: %s", device.getName().c_str()); - } - - std::set capabilities; - - struct v4l2_fmtdesc fmt = { 0 }; - struct v4l2_frmsizeenum frameSize = { 0 }; - - fmt.index = 0; - fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - while (ioctlDevice(v4l2_fd, VIDIOC_ENUM_FMT, &fmt) >= 0) { - VideoCaptureCapability capability; - capability.videoType = toVideoType(fmt.pixelformat); - - frameSize.pixel_format = fmt.pixelformat; - frameSize.index = 0; - - while (ioctlDevice(v4l2_fd, VIDIOC_ENUM_FRAMESIZES, &frameSize) > -1) { - if (frameSize.type == V4L2_FRMSIZE_TYPE_DISCRETE) { - capability.width = frameSize.discrete.width; - capability.height = frameSize.discrete.height; - } - else if (frameSize.type == V4L2_FRMSIZE_TYPE_STEPWISE) { - capability.width = frameSize.stepwise.max_width; - capability.height = frameSize.stepwise.max_height; - } - - v4l2_frmivalenum frameInterval = { 0 }; - frameInterval.pixel_format = fmt.pixelformat; - frameInterval.width = capability.width; - frameInterval.height = capability.height; - - while (ioctlDevice(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &frameInterval) == 0) { - if (frameInterval.type == V4L2_FRMIVAL_TYPE_DISCRETE && frameInterval.discrete.numerator != 0) { - capability.maxFPS = static_cast(static_cast(frameInterval.discrete.denominator) / static_cast(frameInterval.discrete.numerator)); - - capabilities.emplace(capability); - } - else { - capability.maxFPS = static_cast(static_cast(frameInterval.stepwise.max.denominator) / static_cast(frameInterval.stepwise.max.numerator)); - - capabilities.emplace(capability); - } - - frameInterval.index++; - } - - frameSize.index++; - } - fmt.index++; - } - - close(v4l2_fd); - - return capabilities; - } - - void V4l2VideoDeviceManager::run() - { - udev_monitor * mon = udev_monitor_new_from_netlink(udev, "udev"); - - if (!mon) { - RTC_LOG(LS_ERROR) << "V4l2: Failed to init udev monitor"; - return; - } - - udev_monitor_filter_add_match_subsystem_devtype(mon, UDEV_SUBSYSTEM, NULL); - udev_monitor_enable_receiving(mon); - - pollfd items[1]; - items[0].fd = udev_monitor_get_fd(mon); - items[0].events = POLLIN; - - while (running) { - while (poll(items, 1, -1) > 0) { - udev_device * dev = udev_monitor_receive_device(mon); - - if (!dev) { - RTC_LOG(LS_ERROR) << "V4l2: No device received from udev monitor"; - continue; - } - - const char * subsystem = udev_device_get_subsystem(dev); - - if (strcmp(subsystem, UDEV_SUBSYSTEM) != 0) { - udev_device_unref(dev); - continue; - } - - const char * action = udev_device_get_action(dev); - const char * node = udev_device_get_devnode(dev); - const char * name = udev_device_get_property_value(dev, "ID_V4L_PRODUCT"); - - if (strcmp(action, UDEV_ADD) == 0 && checkDevice(node)) { - addDevice(name, node); - } - else if (strcmp(action, UDEV_REMOVE) == 0) { - removeDevice(name, node); - } - - udev_device_unref(dev); - } - } - - udev_monitor_unref(mon); - } - - void V4l2VideoDeviceManager::addDevice(const std::string & name, const std::string & descriptor) - { - auto device = std::make_shared(name, descriptor); - captureDevices.insertDevice(device); - - notifyDeviceConnected(device); - } - - void V4l2VideoDeviceManager::removeDevice(const std::string & name, const std::string & descriptor) - { - auto predicate = [name, descriptor](const VideoDevicePtr & dev) { - return dev->getName() == name && dev->getDescriptor() == descriptor; - }; - - VideoDevicePtr removed = captureDevices.removeDevice(predicate); - - if (removed) { - notifyDeviceDisconnected(removed); - } - } - - bool V4l2VideoDeviceManager::checkDevice(const std::string & descriptor) - { - int v4l2_fd = open(descriptor.c_str(), O_RDONLY); - if (v4l2_fd < 0) { - return false; - } - - struct v4l2_fmtdesc fmt = { 0 }; - fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - bool error = false; - - if (ioctlDevice(v4l2_fd, VIDIOC_ENUM_FMT, &fmt) == -1) { - error = true; - } - - close(v4l2_fd); - - return !error; - } - - int V4l2VideoDeviceManager::ioctlDevice(int fh, int request, void * arg) - { - int r; - - do { - r = ioctl(fh, request, arg); - } - while (-1 == r && ((errno == EINTR) || (errno == EAGAIN) || (errno == ETIMEDOUT))); - - return r; - } - - webrtc::VideoType V4l2VideoDeviceManager::toVideoType(const std::uint32_t & v4l2MediaType) - { - static const MediaFormatConfiguration mediaTypeMap[] = { - {V4L2_PIX_FMT_YUV420, webrtc::VideoType::kI420}, - {V4L2_PIX_FMT_YUYV, webrtc::VideoType::kYUY2}, - {V4L2_PIX_FMT_UYVY, webrtc::VideoType::kUYVY}, - {V4L2_PIX_FMT_YUV420, webrtc::VideoType::kIYUV}, - {V4L2_PIX_FMT_RGB24, webrtc::VideoType::kRGB24}, - {V4L2_PIX_FMT_BGR32, webrtc::VideoType::kBGRA}, - {V4L2_PIX_FMT_RGB32, webrtc::VideoType::kARGB}, - {V4L2_PIX_FMT_MJPEG, webrtc::VideoType::kMJPEG}, - {V4L2_PIX_FMT_YVU420, webrtc::VideoType::kYV12} - }; - - for (const auto & mediaMapping : mediaTypeMap) { - if (mediaMapping.v4l2MediaType == v4l2MediaType) { - return mediaMapping.videoType; - } - } - - return webrtc::VideoType::kUnknown; - } - } -} diff --git a/webrtc-jni/src/main/cpp/src/media/video/macos/AVFVideoDeviceManager.cpp b/webrtc-jni/src/main/cpp/src/media/video/macos/AVFVideoDeviceManager.cpp deleted file mode 100644 index bf87f1b..0000000 --- a/webrtc-jni/src/main/cpp/src/media/video/macos/AVFVideoDeviceManager.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/video/macos/AVFVideoDeviceManager.h" - -#include "rtc_base/logging.h" - -namespace jni -{ - namespace avdev - { - AVFVideoDeviceManager::AVFVideoDeviceManager() : - VideoDeviceManager() - { - // Set up hot-plug listeners. - NSNotificationCenter * notificationCenter = [NSNotificationCenter defaultCenter]; - - void (^deviceConnectedBlock)(NSNotification *) = ^(NSNotification * notification) { - AVCaptureDevice * device = [notification object]; - onDeviceConnected(device); - }; - - void (^deviceDisconnectedBlock)(NSNotification *) = ^(NSNotification * notification) { - AVCaptureDevice * device = [notification object]; - onDeviceDisconnected(device); - }; - - devConnectObserver = [notificationCenter addObserverForName: AVCaptureDeviceWasConnectedNotification - object: nil - queue: [NSOperationQueue mainQueue] - usingBlock: deviceConnectedBlock]; - - devDisconnectObserver = [notificationCenter addObserverForName: AVCaptureDeviceWasDisconnectedNotification - object: nil - queue: [NSOperationQueue mainQueue] - usingBlock: deviceDisconnectedBlock]; - } - - AVFVideoDeviceManager::~AVFVideoDeviceManager() - { - NSNotificationCenter * notificationCenter = [NSNotificationCenter defaultCenter]; - [notificationCenter removeObserver: devConnectObserver]; - [notificationCenter removeObserver: devDisconnectObserver]; - } - - std::set AVFVideoDeviceManager::getVideoCaptureDevices() - { - if (captureDevices.empty()) { - AVCaptureDeviceDiscoverySession * discoverySession = [AVCaptureDeviceDiscoverySession - discoverySessionWithDeviceTypes:@[ - AVCaptureDeviceTypeBuiltInWideAngleCamera, -#if (MAC_OS_X_VERSION_MIN_REQUIRED >= 130000) - AVCaptureDeviceTypeDeskViewCamera, -#endif -#if (MAC_OS_X_VERSION_MIN_REQUIRED >= 140000) - AVCaptureDeviceTypeExternal -#else - AVCaptureDeviceTypeExternalUnknown -#endif - ] - mediaType: AVMediaTypeVideo - position: AVCaptureDevicePositionUnspecified]; - - NSArray * devices = discoverySession.devices; - - for (AVCaptureDevice * device in devices) { - insertDevice(device, false); - } - } - - return captureDevices.devices(); - } - - std::set AVFVideoDeviceManager::getVideoCaptureCapabilities(const VideoDevice & device) - { - std::set capabilities; - - NSString * deviceID = [NSString stringWithUTF8String: device.getDescriptor().c_str()]; - AVCaptureDevice * dev = [AVCaptureDevice deviceWithUniqueID: deviceID]; - NSArray * devFormats = [dev formats]; - - for (AVCaptureDeviceFormat * format in devFormats) { - const CMVideoDimensions dimension = CMVideoFormatDescriptionGetDimensions(format.formatDescription); - const FourCharCode fcc = CMFormatDescriptionGetMediaSubType(format.formatDescription); - - AVFrameRateRange * bestFrameRateRange = nil; - - for (AVFrameRateRange * range in format.videoSupportedFrameRateRanges) { - if (range.maxFrameRate > bestFrameRateRange.maxFrameRate) { - bestFrameRateRange = range; - } - } - - VideoCaptureCapability capability; - capability.width = dimension.width; - capability.height = dimension.height; - capability.maxFPS = static_cast(bestFrameRateRange.maxFrameRate); - capability.videoType = toVideoType(fcc); - capabilities.insert(capability); - } - - return capabilities; - } - - void AVFVideoDeviceManager::insertDevice(AVCaptureDevice * device, bool notify) - { - std::string name([[device localizedName] cStringUsingEncoding: NSUTF8StringEncoding]); - std::string desc([[device uniqueID] cStringUsingEncoding: NSUTF8StringEncoding]); - - auto captureDevice = std::make_shared(name, desc); - - captureDevices.insertDevice(captureDevice); - - // Update default device. - AVCaptureDevice * defaultDevice = [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo]; - NSString * defaultID = [defaultDevice uniqueID]; - - if ([defaultID isEqualToString: [device uniqueID]]) { - setDefaultCaptureDevice(captureDevice); - } - - if (notify) { - notifyDeviceConnected(captureDevice); - } - } - - void AVFVideoDeviceManager::removeDevice(AVCaptureDevice * device, bool notify) - { - std::string desc([[device uniqueID] cStringUsingEncoding: NSUTF8StringEncoding]); - - auto predicate = [desc](const VideoDevicePtr & dev) { return desc == dev->getDescriptor(); }; - VideoDevicePtr removed = captureDevices.removeDevice(predicate); - - if (removed == nullptr) { - std::string name([[device localizedName] cStringUsingEncoding: NSUTF8StringEncoding]); - - RTC_LOG(LS_WARNING) << "AVFoundation: Remove device [" << name.c_str() << "] failed"; - return; - } - - // Update default device. - AVCaptureDevice * defaultDevice = [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo]; - VideoDevicePtr defaultCapture = nullptr; - - if (defaultDevice) { - std::string desc([[defaultDevice uniqueID] cStringUsingEncoding: NSUTF8StringEncoding]); - - auto predicate = [desc](const VideoDevicePtr & dev) { return desc == dev->getDescriptor(); }; - defaultCapture = captureDevices.findDevice(predicate); - } - - setDefaultCaptureDevice(defaultCapture); - - if (notify) { - notifyDeviceDisconnected(removed); - } - } - - void AVFVideoDeviceManager::onDeviceConnected(AVCaptureDevice * device) - { - if ([device hasMediaType: AVMediaTypeVideo]) { - insertDevice(device, true); - } - } - - void AVFVideoDeviceManager::onDeviceDisconnected(AVCaptureDevice * device) - { - if ([device hasMediaType: AVMediaTypeVideo]) { - removeDevice(device, true); - } - } - - webrtc::VideoType AVFVideoDeviceManager::toVideoType(const std::uint32_t & fourCC) - { - switch (fourCC) { - case kCMPixelFormat_32ARGB: - return webrtc::VideoType::kBGRA; - - case kCMPixelFormat_32BGRA: - return webrtc::VideoType::kARGB; - - case kCMPixelFormat_24RGB: - return webrtc::VideoType::kRGB24; - - case kCMPixelFormat_16LE565: - return webrtc::VideoType::kRGB565; - - case kCMPixelFormat_422YpCbCr8: - return webrtc::VideoType::kUYVY; - - case kCMPixelFormat_422YpCbCr8_yuvs: - return webrtc::VideoType::kYUY2; - - case kCMVideoCodecType_JPEG_OpenDML: - return webrtc::VideoType::kMJPEG; - - case kCVPixelFormatType_420YpCbCr8Planar: - case kCVPixelFormatType_420YpCbCr8PlanarFullRange: - return webrtc::VideoType::kI420; - - default: - return webrtc::VideoType::kUnknown; - } - } - } -} diff --git a/webrtc-jni/src/main/cpp/src/media/video/macos/VideoCaptureMac.cpp b/webrtc-jni/src/main/cpp/src/media/video/macos/VideoCaptureMac.cpp deleted file mode 100644 index 8811bd9..0000000 --- a/webrtc-jni/src/main/cpp/src/media/video/macos/VideoCaptureMac.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/video/macos/VideoCaptureMac.h" -#include "Exception.h" - -#include "base/RTCLogging.h" -#include "sdk/objc/components/video_frame_buffer/RTCCVPixelBuffer.h" -#include "sdk/objc/native/src/objc_frame_buffer.h" - - -@interface VideoCaptureCallback () -@property(nonatomic) jni::VideoCaptureMac * videoCapturer; -@end - -@implementation VideoCaptureCallback - -@synthesize videoCapturer = _videoCapturer; - -- (void)capturer:(RTC_OBJC_TYPE(RTCVideoCapturer) *)capturer - didCaptureVideoFrame:(RTC_OBJC_TYPE(RTCVideoFrame) *)frame { - _videoCapturer->OnCapturedFrame(frame); -} - -@end - - -namespace jni -{ - VideoCaptureMac::VideoCaptureMac() : VideoCaptureBase(), - cameraVideoCapturer(nullptr) - { - } - - VideoCaptureMac::~VideoCaptureMac() - { - destroy(); - } - - void VideoCaptureMac::start() - { - if (!device) { - throw new Exception("Video device must be set"); - } - - AVCaptureDevice * captureDevice = nullptr; - - AVCaptureDeviceDiscoverySession * captureDeviceDiscoverySession = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:@[ - AVCaptureDeviceTypeBuiltInWideAngleCamera, -#if (MAC_OS_X_VERSION_MIN_REQUIRED >= 140000) - AVCaptureDeviceTypeExternal -#else - AVCaptureDeviceTypeExternalUnknown -#endif - ] - mediaType:AVMediaTypeVideo - position:AVCaptureDevicePositionUnspecified]; - - for (AVCaptureDevice * avDevice in captureDeviceDiscoverySession.devices) { - if ([avDevice.localizedName isEqualToString:[NSString stringWithUTF8String:device->getName().c_str()]]) { - captureDevice = avDevice; - break; - } - } - - if (!captureDevice) { - throw new Exception("No video capture devices available"); - } - - VideoCaptureCallback * callback = [[VideoCaptureCallback alloc] init]; - callback.videoCapturer = this; - - cameraVideoCapturer = [[RTCCameraVideoCapturer alloc] initWithDelegate:callback]; - - AVCaptureDeviceFormat * selectedFormat = nullptr; - int currentDiff = INT_MAX; - int targetWidth = capability.width; - int targetHeight = capability.height; - - for (AVCaptureDeviceFormat * format in captureDevice.formats) { - CMVideoDimensions dimension = CMVideoFormatDescriptionGetDimensions(format.formatDescription); - FourCharCode pixelFormat = CMFormatDescriptionGetMediaSubType(format.formatDescription); - - int diff = abs(targetWidth - dimension.width) + abs(targetHeight - dimension.height); - if (diff < currentDiff) { - selectedFormat = format; - currentDiff = diff; - } - else if (diff == currentDiff && pixelFormat == [cameraVideoCapturer preferredOutputPixelFormat]) { - selectedFormat = format; - } - } - - if (!selectedFormat) { - selectedFormat = captureDevice.activeFormat; - } - - if (!cameraVideoCapturer) { - std::string deviceName = captureDevice.localizedName.UTF8String; - throw new Exception("Create VideoCaptureModule for UID %s failed", deviceName.c_str()); - } - - void (^CaptureCompletionHandler)(NSError * _Nullable error) = ^(NSError * _Nullable error) { - if (error) { - RTCLogError(@"Failed to start capture: %@", error.localizedDescription); - } - else { - RTCLogInfo(@"Capture started successfully"); - } - }; - - [cameraVideoCapturer startCaptureWithDevice:captureDevice - format:selectedFormat - fps:capability.maxFPS - completionHandler:CaptureCompletionHandler]; - } - - void VideoCaptureMac::stop() - { - destroy(); - } - - void VideoCaptureMac::destroy() - { - if (!cameraVideoCapturer) { - return; - } - - [cameraVideoCapturer stopCapture]; - cameraVideoCapturer = nullptr; - } - - void VideoCaptureMac::OnCapturedFrame(RTC_OBJC_TYPE(RTCVideoFrame) * frame) { - if (!sink) { - return; - } - - const int64_t timestamp_us = frame.timeStampNs / webrtc::kNumNanosecsPerMicrosec; - const int64_t translated_timestamp_us = timestamp_aligner.TranslateTimestamp(timestamp_us, webrtc::TimeMicros()); - - webrtc::scoped_refptr buffer = webrtc::make_ref_counted(frame.buffer); - - sink->OnFrame(webrtc::VideoFrame::Builder() - .set_video_frame_buffer(buffer) - .set_rotation(webrtc::kVideoRotation_0) - .set_timestamp_us(translated_timestamp_us) - .build()); - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/video/macos/VideoTrackDeviceSourceMac.cpp b/webrtc-jni/src/main/cpp/src/media/video/macos/VideoTrackDeviceSourceMac.cpp deleted file mode 100644 index a59ba1e..0000000 --- a/webrtc-jni/src/main/cpp/src/media/video/macos/VideoTrackDeviceSourceMac.cpp +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "media/video/macos/VideoTrackDeviceSourceMac.h" -#include "Exception.h" - -#include "api/video/i420_buffer.h" - -#include "base/RTCLogging.h" -#include "sdk/objc/components/video_frame_buffer/RTCCVPixelBuffer.h" -#include "sdk/objc/native/src/objc_frame_buffer.h" - - -@interface VideoTrackDeviceSourceCallback () -@property(nonatomic) jni::VideoTrackDeviceSourceMac * videoTrackSource; -@end - -@implementation VideoTrackDeviceSourceCallback - -@synthesize videoTrackSource = _videoTrackSource; - -- (void)capturer:(RTC_OBJC_TYPE(RTCVideoCapturer) *)capturer - didCaptureVideoFrame:(RTC_OBJC_TYPE(RTCVideoFrame) *)frame { - _videoTrackSource->OnCapturedFrame(frame); -} - -@end - - -namespace jni -{ - VideoTrackDeviceSourceMac::VideoTrackDeviceSourceMac() : - AdaptedVideoTrackSource(), - VideoTrackDeviceSourceBase(), - cameraVideoCapturer(nullptr) - { - } - - VideoTrackDeviceSourceMac::~VideoTrackDeviceSourceMac() - { - destroy(); - } - - void VideoTrackDeviceSourceMac::start() - { - AVCaptureDevice * captureDevice = nullptr; - - AVCaptureDeviceDiscoverySession * captureDeviceDiscoverySession = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:@[ - AVCaptureDeviceTypeBuiltInWideAngleCamera, - AVCaptureDeviceTypeExternalUnknown - ] - mediaType:AVMediaTypeVideo - position:AVCaptureDevicePositionUnspecified]; - - NSArray * devices = captureDeviceDiscoverySession.devices; - - if (!device && devices.count > 0) { - // No user-defined capture device. Select first available device. - captureDevice = devices[0]; - } - else { - // Use user-defined capture device. - for (AVCaptureDevice * avDevice in devices) { - if ([avDevice.localizedName isEqualToString:[NSString stringWithUTF8String:device->getName().c_str()]]) { - captureDevice = avDevice; - break; - } - } - } - - if (!captureDevice) { - throw new Exception("No video capture devices available"); - } - - VideoTrackDeviceSourceCallback * callback = [[VideoTrackDeviceSourceCallback alloc] init]; - callback.videoTrackSource = this; - - cameraVideoCapturer = [[RTCCameraVideoCapturer alloc] initWithDelegate:callback]; - - AVCaptureDeviceFormat * selectedFormat = nullptr; - int currentDiff = INT_MAX; - int targetWidth = capability.width; - int targetHeight = capability.height; - - for (AVCaptureDeviceFormat * format in captureDevice.formats) { - CMVideoDimensions dimension = CMVideoFormatDescriptionGetDimensions(format.formatDescription); - FourCharCode pixelFormat = CMFormatDescriptionGetMediaSubType(format.formatDescription); - - int diff = abs(targetWidth - dimension.width) + abs(targetHeight - dimension.height); - if (diff < currentDiff) { - selectedFormat = format; - currentDiff = diff; - } - else if (diff == currentDiff && pixelFormat == [cameraVideoCapturer preferredOutputPixelFormat]) { - selectedFormat = format; - } - - } - - if (!selectedFormat) { - selectedFormat = captureDevice.activeFormat; - } - - void (^CaptureCompletionHandler)(NSError * _Nullable error) = ^(NSError * _Nullable error) { - if (error) { - RTCLogError(@"Failed to start capture: %@", error.localizedDescription); - } - else { - RTCLogInfo(@"Capture started successfully"); - } - }; - - [cameraVideoCapturer startCaptureWithDevice:captureDevice - format:selectedFormat - fps:capability.maxFPS - completionHandler:CaptureCompletionHandler]; - } - - void VideoTrackDeviceSourceMac::stop() - { - if (!cameraVideoCapturer) { - return; - } - - [cameraVideoCapturer stopCapture]; - } - - void VideoTrackDeviceSourceMac::destroy() - { - stop(); - - cameraVideoCapturer = nullptr; - } - - bool VideoTrackDeviceSourceMac::is_screencast() const { - return false; - } - - std::optional VideoTrackDeviceSourceMac::needs_denoising() const { - return false; - } - - webrtc::MediaSourceInterface::SourceState VideoTrackDeviceSourceMac::state() const { - return SourceState::kLive; - } - - bool VideoTrackDeviceSourceMac::remote() const { - return false; - } - - void VideoTrackDeviceSourceMac::OnCapturedFrame(RTC_OBJC_TYPE(RTCVideoFrame) * frame) { - const int64_t timestamp_us = frame.timeStampNs / webrtc::kNumNanosecsPerMicrosec; - const int64_t translated_timestamp_us = timestamp_aligner.TranslateTimestamp(timestamp_us, webrtc::TimeMicros()); - - int adapted_width; - int adapted_height; - int crop_width; - int crop_height; - int crop_x; - int crop_y; - - if (!AdaptFrame(frame.width, frame.height, - timestamp_us, - &adapted_width, &adapted_height, - &crop_width, &crop_height, &crop_x, &crop_y)) { - return; - } - - webrtc::scoped_refptr buffer; - - if (adapted_width == frame.width && adapted_height == frame.height) { - // No adaption - optimized path. - buffer = webrtc::make_ref_counted(frame.buffer); - } - else if ([frame.buffer isKindOfClass:[RTC_OBJC_TYPE(RTCCVPixelBuffer) class]]) { - // Adapted CVPixelBuffer frame. - RTC_OBJC_TYPE(RTCCVPixelBuffer) *rtcPixelBuffer = (RTC_OBJC_TYPE(RTCCVPixelBuffer) *)frame.buffer; - buffer = webrtc::make_ref_counted([[RTC_OBJC_TYPE(RTCCVPixelBuffer) alloc] - initWithPixelBuffer:rtcPixelBuffer.pixelBuffer - adaptedWidth:adapted_width - adaptedHeight:adapted_height - cropWidth:crop_width - cropHeight:crop_height - cropX:crop_x + rtcPixelBuffer.cropX - cropY:crop_y + rtcPixelBuffer.cropY]); - } - else { - // Adapted I420 frame. - webrtc::scoped_refptr i420_buffer = webrtc::I420Buffer::Create(adapted_width, adapted_height); - buffer = webrtc::make_ref_counted(frame.buffer); - i420_buffer->CropAndScaleFrom(*buffer->ToI420(), crop_x, crop_y, crop_width, crop_height); - buffer = i420_buffer; - } - - OnFrame(webrtc::VideoFrame::Builder() - .set_video_frame_buffer(buffer) - .set_rotation(webrtc::kVideoRotation_0) - .set_timestamp_us(translated_timestamp_us) - .build()); - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/media/video/windows/WindowsVideoDeviceManager.cpp b/webrtc-jni/src/main/cpp/src/media/video/windows/WindowsVideoDeviceManager.cpp deleted file mode 100644 index 936c59c..0000000 --- a/webrtc-jni/src/main/cpp/src/media/video/windows/WindowsVideoDeviceManager.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "Exception.h" -#include "media/video/windows/WindowsVideoDeviceManager.h" -#include "platform/windows/WinUtils.h" - -#include "modules/video_capture/video_capture_factory.h" - -#include -#include -#include - -namespace jni -{ - namespace avdev - { - WindowsVideoDeviceManager::WindowsVideoDeviceManager() : - WinHotplugNotifier(std::list { KSCATEGORY_VIDEO }) - { - start(); - } - - std::set WindowsVideoDeviceManager::getVideoCaptureDevices() - { - if (captureDevices.empty()) { - enumerateDevices(nullptr); - } - - return captureDevices.devices(); - } - - std::set WindowsVideoDeviceManager::getVideoCaptureCapabilities(const VideoDevice & device) - { - std::set capabilities; - - std::unique_ptr info(webrtc::VideoCaptureFactory::CreateDeviceInfo()); - - if (!info) { - throw jni::Exception("Create video DeviceInfo failed"); - } - - const std::string guid = device.getDescriptor(); - - uint32_t capabilitiesCount = info->NumberOfCapabilities(guid.data()); - - if (capabilitiesCount > 0) { - for (uint32_t i = 0; i < capabilitiesCount; ++i) { - webrtc::VideoCaptureCapability capability; - - if (info->GetCapability(guid.data(), i, capability) == 0) { - VideoCaptureCapability cap; - cap.width = capability.width; - cap.height = capability.height; - cap.maxFPS = capability.maxFPS; - cap.videoType = capability.videoType; - - capabilities.emplace(cap); - } - } - } - - return capabilities; - } - - void WindowsVideoDeviceManager::enumerateDevices(std::wstring * symLink) - { - std::unique_ptr info(webrtc::VideoCaptureFactory::CreateDeviceInfo()); - - if (!info) { - throw jni::Exception("Create video DeviceInfo failed"); - } - - uint32_t deviceCount = info->NumberOfDevices(); - - if (deviceCount > 0) { - // fix duplicated item when device reconect to port. The comparator does not always work correctly. - captureDevices.clearDevices(); - const uint32_t size = webrtc::kVideoCaptureDeviceNameLength; - - for (uint32_t i = 0; i < deviceCount; ++i) { - char name[size] = { 0 }; - char guid[size] = { 0 }; - - if (info->GetDeviceName(i, name, size, guid, size) == 0) { - std::shared_ptr device = std::make_shared(name, guid); - - insertVideoDevice(device); - } - } - } - } - - bool WindowsVideoDeviceManager::insertVideoDevice(VideoDevicePtr device) - { - if (device == nullptr) { - return false; - } - - captureDevices.insertDevice(device); - - return true; - } - - void WindowsVideoDeviceManager::onDeviceConnected(std::wstring symLink) - { - enumerateDevices(&symLink); - } - - void WindowsVideoDeviceManager::onDeviceDisconnected(std::wstring symLink) - { - auto predicate = [symLink](const VideoDevicePtr & dev) { - std::wstring link = UTF8Decode(dev->getDescriptor()); - std::transform(link.begin(), link.end(), link.begin(), ::tolower); - - // IMFActivate and the device broadcaster return different - // symbolic links. Compare only the device instance id. - size_t pos = link.find(L"#{", 0); - pos = (pos == -1) ? (std::min)(link.length(), symLink.length()) : pos; - - return symLink.compare(0, pos, link, 0, pos) == 0; - }; - - VideoDevicePtr removed = captureDevices.removeDevice(predicate); - - if (removed) { - notifyDeviceDisconnected(removed); - } - } - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/platform/macos/MacUtils.cpp b/webrtc-jni/src/main/cpp/src/platform/macos/MacUtils.cpp deleted file mode 100644 index 99286dc..0000000 --- a/webrtc-jni/src/main/cpp/src/platform/macos/MacUtils.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2022 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "platform/macos/MacUtils.h" - -#include - -namespace jni -{ - const std::string CFStringRefToUTF8(CFStringRef stringRef) { - CFIndex length = CFStringGetLength(stringRef); - - if (length == 0) { - return std::string(); - } - - CFRange range = CFRangeMake(0, length); - CFIndex outputSize; - CFIndex converted = CFStringGetBytes(stringRef, range, kCFStringEncodingUTF8, 0, false, nullptr, 0, &outputSize); - - if (converted == 0 || outputSize <= 0) { - return std::string(); - } - - size_t elements = static_cast(outputSize) * sizeof(UInt8) / sizeof(char) + 1; - - std::vector buffer(elements); - - converted = CFStringGetBytes(stringRef, range, kCFStringEncodingUTF8, 0, false, - reinterpret_cast(&buffer[0]), outputSize, nullptr); - - if (converted == 0) { - return std::string(); - } - - // Terminate string. - buffer[elements - 1] = '\0'; - - return std::string(&buffer[0], elements - 1); - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/platform/windows/ComInitializer.cpp b/webrtc-jni/src/main/cpp/src/platform/windows/ComInitializer.cpp deleted file mode 100644 index 71a4637..0000000 --- a/webrtc-jni/src/main/cpp/src/platform/windows/ComInitializer.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "platform/windows/ComInitializer.h" -#include "platform/windows/WinUtils.h" - -#include - -namespace jni -{ - ComInitializer::ComInitializer() : initialized(false) - { - HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); - - if (hr != RPC_E_CHANGED_MODE) { - THROW_IF_FAILED(hr, "Initialize COM failed"); - - initialized = true; - } - } - - ComInitializer::~ComInitializer() - { - if (initialized) { - CoUninitialize(); - } - } - - bool ComInitializer::isInitialized() - { - return initialized; - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/platform/windows/MFInitializer.cpp b/webrtc-jni/src/main/cpp/src/platform/windows/MFInitializer.cpp deleted file mode 100644 index b9a0667..0000000 --- a/webrtc-jni/src/main/cpp/src/platform/windows/MFInitializer.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "platform/windows/MFInitializer.h" -#include "platform/windows/WinUtils.h" - -#include - -namespace jni -{ - MFInitializer::MFInitializer() : initialized(false) - { - HRESULT hr = MFStartup(MF_VERSION, MFSTARTUP_LITE); - THROW_IF_FAILED(hr, "Initialize Media Foundation failed."); - - initialized = true; - } - - MFInitializer::~MFInitializer() - { - if (initialized) { - MFShutdown(); - } - } - - bool MFInitializer::isInitialized() - { - return initialized; - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/platform/windows/MFUtils.cpp b/webrtc-jni/src/main/cpp/src/platform/windows/MFUtils.cpp deleted file mode 100644 index 406b53d..0000000 --- a/webrtc-jni/src/main/cpp/src/platform/windows/MFUtils.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "platform/windows/MFUtils.h" -#include "platform/windows/WinUtils.h" -#include "platform/windows/ComPtr.h" - -#include -#include -#include -#include - -namespace jni -{ - namespace mf - { - const void CreateMediaSource(GUID mediaType, std::string symlink, IMFMediaSource ** source) - { - ComPtr mediaSource; - ComPtr attributes; - GUID sourceType; - GUID idKey; - HRESULT hr; - - std::wstring link = UTF8Decode(symlink); - - hr = MFCreateAttributes(&attributes, 2); - THROW_IF_FAILED(hr, "MMF: Create attributes failed"); - - if (mediaType == MFMediaType_Audio) { - sourceType = MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID; - idKey = MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID; - } - else if (mediaType == MFMediaType_Video) { - sourceType = MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID; - idKey = MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK; - } - else { - throw Exception("MMF: Media type is not supported"); - } - - hr = attributes->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, sourceType); - THROW_IF_FAILED(hr, "MMF: Set source type failed"); - - hr = attributes->SetString(idKey, link.c_str()); - THROW_IF_FAILED(hr, "MMF: Set source ID key failed"); - - hr = MFCreateDeviceSource(attributes, &mediaSource); - THROW_IF_FAILED(hr, "MMF: Create video source failed"); - - *source = mediaSource; - (*source)->AddRef(); - } - - const webrtc::VideoType toVideoType(const GUID & mfMediaType) - { - static const MediaFormatConfiguration mediaTypeMap[] = { - {MFVideoFormat_I420, webrtc::VideoType::kI420}, - {MFVideoFormat_YUY2, webrtc::VideoType::kYUY2}, - {MFVideoFormat_UYVY, webrtc::VideoType::kUYVY}, - {MFVideoFormat_IYUV, webrtc::VideoType::kIYUV}, - {MFVideoFormat_RGB24, webrtc::VideoType::kRGB24}, - {MFVideoFormat_RGB32, webrtc::VideoType::kBGRA}, - {MFVideoFormat_ARGB32, webrtc::VideoType::kARGB}, - {MFVideoFormat_MJPG, webrtc::VideoType::kMJPEG}, - {MFVideoFormat_YV12, webrtc::VideoType::kYV12} - }; - - for (const auto & mediaMapping : mediaTypeMap) { - if (mediaMapping.mfMediaType == mfMediaType) { - return mediaMapping.videoType; - } - } - - return webrtc::VideoType::kUnknown; - } - } -} \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/platform/windows/WinHotplugNotifier.cpp b/webrtc-jni/src/main/cpp/src/platform/windows/WinHotplugNotifier.cpp deleted file mode 100644 index 1a8fafb..0000000 --- a/webrtc-jni/src/main/cpp/src/platform/windows/WinHotplugNotifier.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "platform/windows/WinHotplugNotifier.h" -#include "platform/windows/WinUtils.h" - -#include -#include -#include -#include -#include -#include - -#include "rtc_base/logging.h" - -namespace jni -{ - WinHotplugNotifier::WinHotplugNotifier(std::list devInterfaces) : - deviceInterfaces(devInterfaces), - hWnd(nullptr), - threadHandle(nullptr) - { - } - - WinHotplugNotifier::~WinHotplugNotifier() - { - stop(); - } - - void WinHotplugNotifier::start() - { - threadHandle = CreateThread(nullptr, 0, run, this, 0, nullptr); - } - - void WinHotplugNotifier::stop() - { - PostMessage(hWnd, WM_CLOSE, 0, 0); - - if (threadHandle != nullptr) { - WaitForSingleObject(threadHandle, INFINITE); - CloseHandle(threadHandle); - threadHandle = nullptr; - } - } - - DWORD WINAPI WinHotplugNotifier::run(void * context) - { - WinHotplugNotifier * notifier = static_cast(context); - - if (!notifier->initializeWindow()) { - RTC_LOG(LS_ERROR) << "MMF: Initialize notification window failed"; - return 0; - } - if (!notifier->registerForDeviceNotification()) { - RTC_LOG(LS_INFO) << "MMF: Register for device notification failed"; - return 0; - } - - MSG msg = { 0 }; - - while (GetMessage(&msg, notifier->hWnd, 0, 0)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - return 0; - } - - bool WinHotplugNotifier::initializeWindow() - { - HINSTANCE hInstance = GetModuleHandle(nullptr); - - WNDCLASSEX wcex = { 0 }; - wcex.cbSize = sizeof(WNDCLASSEX); - wcex.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; - wcex.lpfnWndProc = WinHotplugNotifier::wndProc; - wcex.cbClsExtra = 0; - wcex.cbWndExtra = 0; - wcex.hInstance = hInstance; - wcex.hIcon = NULL; - wcex.hCursor = NULL; - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW); - wcex.lpszMenuName = NULL; - wcex.lpszClassName = CLASS_NAME; - wcex.hIconSm = NULL; - - if (!RegisterClassEx(&wcex)) { - return false; - } - - hWnd = CreateWindow(CLASS_NAME, WINDOW_NAME, WS_ICONIC, 0, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr); - - if (!hWnd) { - return false; - } - - SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast(this)); - - ShowWindow(hWnd, SW_HIDE); - UpdateWindow(hWnd); - - return true; - } - - bool WinHotplugNotifier::registerForDeviceNotification() - { - DEV_BROADCAST_DEVICEINTERFACE di = { 0 }; - di.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); - di.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; - - for (GUID & devInterface : deviceInterfaces) { - di.dbcc_classguid = devInterface; - - HDEVNOTIFY handle = RegisterDeviceNotification(hWnd, &di, DEVICE_NOTIFY_WINDOW_HANDLE); - - if (handle != nullptr) { - deviceNotifyHandles.push_back(handle); - } - else { - RTC_LOG(LS_ERROR) << "Register device notification failed"; - } - } - - return (deviceInterfaces.size() == deviceNotifyHandles.size()); - } - - void WinHotplugNotifier::onClose(HWND hWnd) - { - WinHotplugNotifier * win = reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); - - for (auto i = win->deviceNotifyHandles.begin(); i != win->deviceNotifyHandles.end();) { - HDEVNOTIFY devNotify = *i; - - if (devNotify != nullptr) { - UnregisterDeviceNotification(devNotify); - } - - i = win->deviceNotifyHandles.erase(i); - } - - PostQuitMessage(0); - } - - void WinHotplugNotifier::onDeviceChange(HWND hWnd, WPARAM wParam, LPARAM lParam) - { - if (lParam == 0) { - return; - } - if (wParam == DBT_USERDEFINED) { - return; - } - - // All remaining wParams use DEV_BROADCAST_HDR. - auto header = reinterpret_cast(lParam); - - if (header == nullptr) { - return; - } - - if (header->dbch_devicetype != DBT_DEVTYP_DEVICEINTERFACE) { - return; - } - - auto devInterface = reinterpret_cast(lParam); - - if (devInterface == nullptr) { - return; - } - - WinHotplugNotifier * win = reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); - - char buffer[512] = { 0 }; - strncpy_s(buffer, devInterface->dbcc_name, 512); - - std::string symLink(buffer); - std::transform(symLink.begin(), symLink.end(), symLink.begin(), ::tolower); - - std::wstring symLink_w = UTF8Decode(symLink); - - switch (wParam) { - case DBT_DEVICEARRIVAL: - win->onDeviceConnected(symLink_w); - break; - - case DBT_DEVICEREMOVECOMPLETE: - win->onDeviceDisconnected(symLink_w); - break; - } - } - - LRESULT CALLBACK WinHotplugNotifier::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) - { - LRESULT ret = 1; - - switch (message) { - case WM_CLOSE: - onClose(hWnd); - break; - - case WM_DEVICECHANGE: - onDeviceChange(hWnd, wParam, lParam); - break; - - default: - ret = DefWindowProc(hWnd, message, wParam, lParam); - break; - } - - return ret; - } -} \ No newline at end of file diff --git a/webrtc/pom.xml b/webrtc/pom.xml index c767094..6c84184 100644 --- a/webrtc/pom.xml +++ b/webrtc/pom.xml @@ -39,9 +39,6 @@ --add-opens webrtc.java/dev.onvoid.webrtc=ALL-UNNAMED --add-opens webrtc.java/dev.onvoid.webrtc.logging=ALL-UNNAMED - --add-opens webrtc.java/dev.onvoid.webrtc.media=ALL-UNNAMED - --add-opens webrtc.java/dev.onvoid.webrtc.media.audio=ALL-UNNAMED - --add-opens webrtc.java/dev.onvoid.webrtc.media.video=ALL-UNNAMED diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/PeerConnectionFactory.java b/webrtc/src/main/java/dev/onvoid/webrtc/PeerConnectionFactory.java index 5c5b112..356e8b1 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/PeerConnectionFactory.java +++ b/webrtc/src/main/java/dev/onvoid/webrtc/PeerConnectionFactory.java @@ -18,20 +18,10 @@ import dev.onvoid.webrtc.internal.DisposableNativeObject; import dev.onvoid.webrtc.internal.NativeLoader; -import dev.onvoid.webrtc.media.MediaStreamTrack; -import dev.onvoid.webrtc.media.MediaType; -import dev.onvoid.webrtc.media.audio.AudioDeviceModuleBase; -import dev.onvoid.webrtc.media.audio.AudioOptions; -import dev.onvoid.webrtc.media.audio.AudioProcessing; -import dev.onvoid.webrtc.media.audio.AudioTrackSource; -import dev.onvoid.webrtc.media.audio.AudioTrack; -import dev.onvoid.webrtc.media.video.VideoTrackSource; -import dev.onvoid.webrtc.media.video.VideoTrack; /** * The PeerConnectionFactory is the main entry point for a WebRTC application. - * It provides factory methods for {@link RTCPeerConnection} and audio/video - * {@link MediaStreamTrack}s. + * It provides factory methods for {@link RTCPeerConnection}. * * @author Alex Andres */ @@ -64,74 +54,6 @@ public PeerConnectionFactory() { this(null, null); } - /** - * Creates an instance of PeerConnectionFactory with the provided audio - * processing module. - * - * @param audioProcessing The custom audio processing module. - */ - public PeerConnectionFactory(AudioProcessing audioProcessing) { - initialize(null, audioProcessing); - } - - /** - * Creates an instance of PeerConnectionFactory with the provided audio - * device module. - * - * @param audioModule The custom audio device module. - */ - public PeerConnectionFactory(AudioDeviceModuleBase audioModule) { - initialize(audioModule, null); - } - - /** - * Creates an instance of PeerConnectionFactory with provided modules for - * audio devices and audio processing. - * - * @param audioModule The custom audio device module. - * @param audioProcessing The custom audio processing module. - */ - public PeerConnectionFactory(AudioDeviceModuleBase audioModule, - AudioProcessing audioProcessing) { - initialize(audioModule, audioProcessing); - } - - /** - * Creates an {@link AudioTrackSource}. The audio source may be used by one - * or more {@link AudioTrack}s. - * - * @param options Audio options to control the audio processing. - * - * @return The created audio source. - */ - public native AudioTrackSource createAudioSource(AudioOptions options); - - /** - * Creates an new {@link AudioTrack}. The audio track can be added to the - * {@link RTCPeerConnection} using the {@link RTCPeerConnection#addTrack - * addTrack} or {@link RTCPeerConnection#addTransceiver addTransceiver} - * methods. - * - * @param label The identifier string of the audio track. - * @param source The audio source that provides audio data. - * - * @return The created audio track. - */ - public native AudioTrack createAudioTrack(String label, AudioTrackSource source); - - /** - * Creates a new {@link VideoTrack}. The video track can be added to the - * {@link RTCPeerConnection} using the {@link RTCPeerConnection#addTrack - * addTrack} or {@link RTCPeerConnection#addTransceiver addTransceiver} - * methods. - * - * @param label The identifier string of the video track. - * @param source The video source that provides video data. - * - * @return The created video track. - */ - public native VideoTrack createVideoTrack(String label, VideoTrackSource source); - /** * Creates a new {@link RTCPeerConnection}. * @@ -144,32 +66,7 @@ public PeerConnectionFactory(AudioDeviceModuleBase audioModule, public native RTCPeerConnection createPeerConnection( RTCConfiguration config, PeerConnectionObserver observer); - /** - * Returns the capabilities of the system for receiving media of the given - * media type. - * - * @param type The type value must be either {@code AUDIO} or {@code - * VIDEO}. - * - * @return The supported capabilities for an {@link RTCRtpReceiver}. - */ - public native RTCRtpCapabilities getRtpReceiverCapabilities(MediaType type); - - /** - * Returns the capabilities of the system for sending media of the given - * media type. - * - * @param type The type value must be either {@code AUDIO} or {@code - * VIDEO}. - * - * @return The supported capabilities for an {@link RTCRtpSender}. - */ - public native RTCRtpCapabilities getRtpSenderCapabilities(MediaType type); - @Override public native void dispose(); - private native void initialize(AudioDeviceModuleBase audioModule, - AudioProcessing audioProcessing); - } diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/PeerConnectionObserver.java b/webrtc/src/main/java/dev/onvoid/webrtc/PeerConnectionObserver.java index b4ec1f2..70185f2 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/PeerConnectionObserver.java +++ b/webrtc/src/main/java/dev/onvoid/webrtc/PeerConnectionObserver.java @@ -16,8 +16,6 @@ package dev.onvoid.webrtc; -import dev.onvoid.webrtc.media.MediaStream; - /** * RTCPeerConnection callback interface. * @@ -97,22 +95,6 @@ default void onIceCandidateError(RTCPeerConnectionIceErrorEvent event) { default void onIceCandidatesRemoved(RTCIceCandidate[] candidates) { } - /** - * Media is received on a new stream from the remote peer. - * - * @param stream The new media stream. - */ - default void onAddStream(MediaStream stream) { - } - - /** - * The remote peer has closed a stream. - * - * @param stream The closed media stream. - */ - default void onRemoveStream(MediaStream stream) { - } - /** * The remote peer has opened a RTCDataChannel. * @@ -128,46 +110,4 @@ default void onDataChannel(RTCDataChannel dataChannel) { default void onRenegotiationNeeded() { } - /** - * New incoming media has been negotiated for a specific RTCRtpReceiver, and - * that receiver's track has been added to any associated remote - * MediaStreams. - *

- * Note: This is called with both Plan B and Unified Plan semantics. Unified - * Plan users should prefer OnTrack, OnAddTrack is only called as backwards - * compatibility (and is called in the exact same situations as OnTrack). - * - * @param receiver The created RTP receiver. - * @param mediaStreams Associated remote MediaStreams of the negotiated - * media track. - */ - default void onAddTrack(RTCRtpReceiver receiver, MediaStream[] mediaStreams) { - } - - /** - * Called when signaling indicates that media will no longer be received on - * a track. - *

- * With Plan B semantics, the given receiver will have been removed from the - * PeerConnection and the track muted. - *

- * With Unified Plan semantics, the receiver will remain but the transceiver - * will have changed direction to either "SendOnly" or "Inactive". - * - * @param receiver The RTP receiver of the removed track. - */ - default void onRemoveTrack(RTCRtpReceiver receiver) { - } - - /** - * Called when signaling indicates a transceiver will be receiving media - * from the remote peer, as a result of SetRemoteDescription. - *

- * Note: This will only be called if Unified Plan semantics are specified. - * - * @param transceiver The RTP transceiver of the created track. - */ - default void onTrack(RTCRtpTransceiver transceiver) { - } - } diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCDtlsTransport.java b/webrtc/src/main/java/dev/onvoid/webrtc/RTCDtlsTransport.java index 5cce590..f9a71a2 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCDtlsTransport.java +++ b/webrtc/src/main/java/dev/onvoid/webrtc/RTCDtlsTransport.java @@ -28,9 +28,7 @@ * constructed as a result of calls to {@link RTCPeerConnection#setLocalDescription * setLocalDescription} and {@link RTCPeerConnection#setRemoteDescription * setRemoteDescription}. Each RTCDtlsTransport object represents the DTLS - * transport layer for the RTP or RTCP component of a specific {@link - * RTCRtpTransceiver}, or a group of RTCRtpTransceivers if such a group has been - * negotiated via [BUNDLE]. + * transport layer for the RTP. * * @author Alex Andres */ diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCDtmfSender.java b/webrtc/src/main/java/dev/onvoid/webrtc/RTCDtmfSender.java deleted file mode 100644 index dc9412f..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCDtmfSender.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc; - -import dev.onvoid.webrtc.internal.NativeObject; - -/** - * Represents a DTMF (Dual-Tone Multi-Frequency) sender for WebRTC. - * This class allows sending DTMF tones over a WebRTC connection. - *

- * The RTCDtmfSender interface enables the generation of DTMF tones on an audio track. - * This is typically used in Voice over IP (VoIP) applications to send DTMF tones to - * a remote telephony system or interactive voice response (IVR) system. - *

- * DTMF tones are the audible tones generated when pressing keys on a telephone keypad. - * The supported DTMF tones are: 0-9, A-D, *, and #. In addition, the special characters - * ',' (comma) can be used to insert a 2-second delay between tones. - * - * @author Alex Andres - * - * @see W3C WebRTC 1.0: RTCDtmfSender - */ -public class RTCDtmfSender extends NativeObject { - - RTCDtmfSender() { - // Default constructor for native object instantiation. - } - - /** - * Checks whether this RTCDtmfSender is capable of sending DTMF tones. - *

- * This method returns true if and only if the associated RTCRtpSender's - * track is non-null and is of kind "audio". - * To be able to send DTMF, the associated RTCDtmfSender must be able to - * send packets, and a "telephone-event" codec must be negotiated. - *

- * When this method returns false, calling {@link #insertDtmf} will have no effect. - * - * @return true if DTMF tones can be inserted. - */ - public native boolean canInsertDtmf(); - - /** - * Inserts DTMF tones to be transmitted on the audio track. - *

- * The tones parameter is treated as a series of characters. Characters - * 0 through 9, A through D, #, and * generate the associated DTMF tones. - * The characters a through d are equivalent to A through D. The character ',' (comma) - * indicates a delay of 2 seconds before processing the next character in the tones parameter. - *

- * Unrecognized characters in the tones parameter are ignored. - *

- * If {@link #canInsertDtmf} is false, this method will have no effect and return false. - *

- * The duration parameter indicates the duration in milliseconds to use for each - * character passed in the tones parameter. The duration cannot be more than 6000 - * milliseconds or less than 70 milliseconds. The default duration is 100 milliseconds. - *

- * The interToneGap parameter indicates the gap between tones in milliseconds. - * The interToneGap cannot be less than 50 milliseconds. The default value is 50 milliseconds. - * - * @param tones String containing the DTMF tones to be transmitted. - * Valid characters are 0-9, A-D, #, *, and , (comma). - * @param duration Duration in milliseconds for each tone. Must be between 40 and 6000 ms. - * @param interToneGap Gap between tones in milliseconds. Must be at least 30 ms. - * - * @return true if the tones were successfully queued for transmission. - */ - public native boolean insertDtmf(String tones, int duration, int interToneGap); - - /** - * Gets the tones remaining in the transmission queue. - *

- * This method returns the list of DTMF tones that have been queued for transmission - * but not yet sent. This includes any tones currently being transmitted. - *

- * If the value is an empty string, it indicates that there are no tones - * currently queued for transmission. - * - * @return String containing the remaining DTMF tones in the queue, or an empty string if none. - */ - public native String tones(); - - /** - * Gets the current tone duration setting. - *

- * This method returns the current value of the duration parameter that will be used for - * future calls to {@link #insertDtmf}. The duration is the length of time, in milliseconds, - * that each DTMF tone is played. - *

- * The default value is 100 milliseconds. Valid values are between 70 and 6000 milliseconds. - * - * @return The duration in milliseconds for each tone. - */ - public native int duration(); - - /** - * Gets the current gap between tones setting. - *

- * This method returns the current value of the interToneGap parameter that will be used for - * future calls to {@link #insertDtmf}. The interToneGap is the length of time, in milliseconds, - * between the end of one DTMF tone and the start of the next. - *

- * The default value is 50 milliseconds. Valid values must be at least 50 milliseconds but should - * be as short as possible. - * - * @return The gap between tones in milliseconds. - */ - public native int interToneGap(); - - /** - * Registers an observer to receive notifications about DTMF-related events. - *

- * Only one observer can be registered at a time. Registering a new observer - * when one is already registered will replace the existing observer. - * - * @param observer The DTMF sender observer to register. - */ - public native void registerObserver(RTCDtmfSenderObserver observer); - - /** - * Unregisters the previously registered DTMF sender observer. - *

- * After calling this method, no observer will receive notifications about - * DTMF-related events until a new observer is registered. - *

- * If no observer is currently registered, this method has no effect. - */ - public native void unregisterObserver(); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCDtmfSenderObserver.java b/webrtc/src/main/java/dev/onvoid/webrtc/RTCDtmfSenderObserver.java deleted file mode 100644 index b08e2c4..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCDtmfSenderObserver.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc; - -/** - * Observer interface for DTMF (Dual-Tone Multi-Frequency) tone events. - *

- * This interface allows applications to receive notifications when DTMF tones - * are sent by an {@link RTCDtmfSender}. It corresponds to the - * "tonechange" event in the W3C WebRTC specification. - * - * @author Alex Andres - * - * @see RTCDtmfSender - */ -public interface RTCDtmfSenderObserver { - - /** - * Called when a DTMF tone sent by an {@link RTCDtmfSender}. - * - * @param tone The tone being played (one of "0123456789ABCD#*") or an - * empty string if the previous tone has finished playing. - * @param toneBuffer The remaining tones in the queue, including the current tone. - * Empty string if no tones remain. - */ - void onToneChange(String tone, String toneBuffer); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCIceTransport.java b/webrtc/src/main/java/dev/onvoid/webrtc/RTCIceTransport.java index 86f8434..5fc0efa 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCIceTransport.java +++ b/webrtc/src/main/java/dev/onvoid/webrtc/RTCIceTransport.java @@ -25,9 +25,7 @@ * RTCIceTransport objects are constructed as a result of calls to {@link * RTCPeerConnection#setLocalDescription setLocalDescription} and {@link * RTCPeerConnection#setRemoteDescription setRemoteDescription}. Each - * RTCIceTransport object represents the ICE transport layer for the RTP or RTCP - * component of a specific {@link RTCRtpTransceiver}, or a group of - * RTCRtpTransceivers if such a group has been negotiated via [BUNDLE]. + * RTCIceTransport object represents the ICE transport layer for the RTP. * * @author Alex Andres */ diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCPeerConnection.java b/webrtc/src/main/java/dev/onvoid/webrtc/RTCPeerConnection.java index 3bc6fa8..d111ad4 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCPeerConnection.java +++ b/webrtc/src/main/java/dev/onvoid/webrtc/RTCPeerConnection.java @@ -17,7 +17,6 @@ package dev.onvoid.webrtc; import dev.onvoid.webrtc.internal.NativeObject; -import dev.onvoid.webrtc.media.MediaStreamTrack; import java.util.List; @@ -45,72 +44,6 @@ private RTCPeerConnection() { } - /** - * Returns an array of {@link RTCRtpSender} objects representing the RTP - * senders that belong to non-stopped {@link RTCRtpTransceiver} objects - * currently attached to this RTCPeerConnection. - * - * @return An array of RTP senders. - */ - public native RTCRtpSender[] getSenders(); - - /** - * Returns an array of {@link RTCRtpReceiver} objects representing the RTP - * receivers that belong to non-stopped {@link RTCRtpTransceiver} objects - * currently attached to this RTCPeerConnection. - * - * @return An array of RTP receivers. - */ - public native RTCRtpReceiver[] getReceivers(); - - /** - * Returns an array of {@link RTCRtpTransceiver} objects representing the - * RTP transceivers that are currently attached to this RTCPeerConnection. - * - * @return An array of RTP transceivers. - */ - public native RTCRtpTransceiver[] getTransceivers(); - - /** - * Adds a new track to the RTCPeerConnection, and indicates that it is - * contained in the specified MediaStreams. - * - * @param track A MediaStreamTrack representing the media track to - * transmit. - * @param streamIds A list of MediaStream ids to which the track belongs - * to. - * - * @return The RTCRtpSender which will be used to transmit the media data. - */ - public native RTCRtpSender addTrack(MediaStreamTrack track, - List streamIds); - - /** - * Stops sending media from sender. The RTCRtpSender will still appear in - * {@link #getSenders()}. Doing so will cause future calls to {@link - * #createOffer} to mark the media description for the corresponding - * transceiver as {@link RTCRtpTransceiverDirection#RECV_ONLY} or {@link - * RTCRtpTransceiverDirection#INACTIVE}. - * - * @param sender The RTCRtpSender to remove from the connection. - */ - public native void removeTrack(RTCRtpSender sender); - - /** - * Create a new RTCRtpTransceiver and add it to the set of transceivers. - * Adding a transceiver will cause future calls to {@link #createOffer} to - * add a media description for the corresponding transceiver. - * - * @param track A MediaStreamTrack representing the media track to - * transmit. - * @param init The transceiver configuration options. - * - * @return The RTCRtpTransceiver which will be used to transmit and receive - * the media data. - */ - public native RTCRtpTransceiver addTransceiver(MediaStreamTrack track, - RTCRtpTransceiverInit init); - /** * Creates a new RTCDataChannel object with the given label. The * RTCDataChannelInit dictionary can be used to configure properties of the @@ -127,8 +60,7 @@ public native RTCDataChannel createDataChannel(String label, /** * Initiates the creation of an SDP that contains an RFC 3264 offer with the - * supported configurations for the session, including descriptions of the - * local MediaStreamTracks attached to this RTCPeerConnection, the + * supported configurations for the session, the * codec/RTP/RTCP capabilities supported by this implementation, and * parameters of the ICE agent and the DTLS connection. * @@ -142,11 +74,9 @@ public native void createOffer(RTCOfferOptions options, /** * Generates an SDP answer to an offer received from a remote peer with the * supported configuration for the session that is compatible with the - * parameters in the remote configuration. Like {@code createOffer}, the - * returned SDP contains descriptions of the local MediaStreamTracks - * attached to this RTCPeerConnection, the codec/RTP/RTCP options negotiated - * for this session, and any candidates that have been gathered by the ICE - * Agent. + * parameters in the remote configuration. Like {@code createOffer}, + * the codec/RTP/RTCP options negotiated for this session, and any candidates + * that have been gathered by the ICE Agent. * * @param options The options to provide additional control over the * answer. @@ -306,24 +236,6 @@ public native void setRemoteDescription(RTCSessionDescription description, */ public native void getStats(RTCStatsCollectorCallback callback); - /** - * Gathers the current statistics of the specified RTCRtpReceiver. - * - * @param receiver The RTCRtpReceiver of which to gather the stats. - * @param callback The callback to receive the generated stats. - */ - public native void getStats(RTCRtpReceiver receiver, - RTCStatsCollectorCallback callback); - - /** - * Gathers the current statistics of the specified RTCRtpSender. - * - * @param sender The RTCRtpSender of which to gather the stats. - * @param callback The callback to receive the generated stats. - */ - public native void getStats(RTCRtpSender sender, - RTCStatsCollectorCallback callback); - /** * Tells the RTCPeerConnection that ICE should be restarted. Subsequent * calls to {@code createOffer} will create descriptions that will restart diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtcpParameters.java b/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtcpParameters.java deleted file mode 100644 index ef26dc9..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtcpParameters.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc; - -/** - * Provides information on RTCP settings. - * - * @author Alex Andres - */ -public class RTCRtcpParameters { - - /** - * The Canonical Name (CNAME) used by RTCP (e.g. in SDES messages). - */ - public final String cName; - - /** - * Whether reduced size RTCP is configured (if true) or compound RTCP. - */ - public final boolean reducedSize; - - - /** - * Creates an instance of RTCRtcpParameters with the specified canonical - * name and the reduced size flag. - * - * @param cName The Canonical Name used by RTCP. - * @param reducedSize True if reduced size RTCP is configured, false - * otherwise. - */ - public RTCRtcpParameters(String cName, boolean reducedSize) { - this.cName = cName; - this.reducedSize = reducedSize; - } - - @Override - public String toString() { - return String.format("%s [cName=%s, reducedSize=%s]", - RTCRtcpParameters.class.getSimpleName(), cName, reducedSize); - } -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpCapabilities.java b/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpCapabilities.java deleted file mode 100644 index d980321..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpCapabilities.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc; - -import java.util.List; - -/** - * Contains the capabilities of the system for receiving media. The - * RTCRtpCapabilities class is meant to provide a way to discover the types of - * capabilities of the application including which codecs may be supported. - * - * @author Alex Andres - */ -public class RTCRtpCapabilities { - - /** - * Supported media codecs as well as entries for RTX, RED and FEC - * mechanisms. - */ - private final List codecs; - - /** - * Supported RTP header extensions. - */ - private final List headerExtensions; - - - /** - * Creates an instance of RTCRtpCapabilities with the supported codec and - * RTP header extension capabilities. - * - * @param codecs The supported media codecs. - * @param headerExtensions The supported RTP header extensions. - */ - public RTCRtpCapabilities(List codecs, - List headerExtensions) { - this.codecs = codecs; - this.headerExtensions = headerExtensions; - } - - /** - * Returns the supported media codecs as well as entries for RTX, RED and - * FEC mechanisms. - * - * @return The supported media codecs. - */ - public List getCodecs() { - return codecs; - } - - /** - * Returns the supported RTP header extensions. - * - * @return The supported RTP header extensions. - */ - public List getHeaderExtensions() { - return headerExtensions; - } - - @Override - public String toString() { - return String.format("%s [codecs=%s, headerExtensions=%s]", - RTCRtpCapabilities.class.getSimpleName(), codecs, - headerExtensions); - } -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpCodecCapability.java b/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpCodecCapability.java deleted file mode 100644 index 545df5b..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpCodecCapability.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc; - -import dev.onvoid.webrtc.media.MediaType; - -import java.util.Map; - -/** - * Represents the static capabilities of an endpoint's implementation of a - * codec. - * - * @author Alex Andres - */ -public class RTCRtpCodecCapability { - - /** - * The media type of the codec. Equivalent to the MIME top-level type. - */ - private final MediaType mediaType; - - /** - * Used to identify the codec. Equivalent to the MIME subtype. - */ - private final String name; - - /** - * The codec clock rate expressed in Hertz. - */ - private final Integer clockRate; - - /** - * When present, indicates the number of audio channels (mono=1, stereo=2). - *

- * Unused for video codecs. - */ - private final Integer channels; - - /** - * The "format specific parameters" from the "a=fmtp" line in the SDP - * corresponding to the codec. These parameters are named using all - * lowercase strings. Boolean values are represented by the string "1". - */ - private final Map sdpFmtp; - - - /** - * Creates an instance of RTCRtpCodecCapability with the specified - * capability parameters. - * - * @param mediaType The media type of the codec. Equivalent to the MIME - * top-level type. - * @param name The codec name. Equivalent to the MIME subtype. - * @param clockRate The codec clock rate expressed in Hertz. - * @param channels The number of audio channels. Unused for video codecs. - * @param sdpFmtp The "a=fmtp" parameters in the SDP. - */ - public RTCRtpCodecCapability(MediaType mediaType, String name, - Integer clockRate, Integer channels, Map sdpFmtp) { - this.mediaType = mediaType; - this.name = name; - this.clockRate = clockRate; - this.channels = channels; - this.sdpFmtp = sdpFmtp; - } - - /** - * Returns media type of the codec equivalent to the MIME top-level type. - * - * @return The media type of the codec. - */ - public MediaType getMediaType() { - return mediaType; - } - - /** - * Returns the name of the codec equivalent to the MIME subtype. - * - * @return The name of the codec. - */ - public String getName() { - return name; - } - - /** - * Returns the codec clock rate expressed in Hertz. - * - * @return The codec clock rate expressed in Hertz. - */ - public int getClockRate() { - return clockRate; - } - - /** - * Returns the number of audio channels (mono=1, stereo=2). - *

- * Unused for video codecs. - * - * @return The number of audio channels. - */ - public int getChannels() { - return channels; - } - - /** - * Returns the format specific parameters in the SDP corresponding to the - * codec. The map contains the "a=fmtp" line in the SDP for convenient - * access of the values. - * - * @return The format specific parameters in the SDP. - */ - public Map getSDPFmtp() { - return sdpFmtp; - } - - /** - * Returns the MIME type composed of the {@code mediaType} and the {@code - * name}. - * - * @return The codec MIME type. - */ - public String getMimeType() { - return mediaType.toString().toLowerCase() + "/" + name; - } - - @Override - public String toString() { - return String.format("%s [mediaType=%s, name=%s, clockRate=%s, channels=%s, sdpFmtp=%s]", - RTCRtpCodecCapability.class.getSimpleName(), mediaType, name, - clockRate, channels, sdpFmtp); - } -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpCodecParameters.java b/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpCodecParameters.java deleted file mode 100644 index 76a756a..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpCodecParameters.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc; - -import dev.onvoid.webrtc.media.MediaType; - -import java.util.Map; - -/** - * Describes the configuration parameters for a single media codec. - * - * @author Alex Andres - */ -public class RTCRtpCodecParameters { - - /** - * The RTP payload type used to identify this codec. - */ - public final int payloadType; - - /** - * The media type of the codec. Equivalent to the MIME top-level type. - */ - public final MediaType mediaType; - - /** - * Used to identify the codec. Equivalent to the MIME subtype. - */ - public final String codecName; - - /** - * The codec clock rate expressed in Hertz. - */ - public final Integer clockRate; - - /** - * When present, indicates the number of audio channels (mono=1, stereo=2). - */ - public final Integer channels; - - /** - * The "format specific parameters" field from the "a=fmtp" line in the SDP - * corresponding to the codec, if one exists. For an RTCRtpSender, these - * parameters come from the remote description, and for an RTCRtpReceiver, - * they come from the local description. - */ - public final Map parameters; - - - /** - * Creates an instance of RTCRtpCodecParameters with the specified media - * codec parameters. - * - * @param payloadType The RTP payload type used to identify the codec. - * @param mediaType The media type of the codec. - * @param codecName The codec name. Equivalent to the MIME subtype. - * @param clockRate The codec clock rate expressed in Hertz. - * @param channels The number of audio channels. Unused for video codecs. - * @param parameters The "a=fmtp" parameters in the SDP. - */ - public RTCRtpCodecParameters(int payloadType, MediaType mediaType, - String codecName, Integer clockRate, Integer channels, - Map parameters) { - this.payloadType = payloadType; - this.mediaType = mediaType; - this.codecName = codecName; - this.clockRate = clockRate; - this.channels = channels; - this.parameters = parameters; - } - - @Override - public String toString() { - return String.format("%s [payloadType=%s, mediaType=%s, codecName=%s, clockRate=%s, channels=%s, parameters=%s]", - RTCRtpCodecParameters.class.getSimpleName(), payloadType, - mediaType, codecName, clockRate, channels, parameters); - } -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpContributingSource.java b/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpContributingSource.java deleted file mode 100644 index b3395d7..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpContributingSource.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc; - -/** - * Contains information about a given contributing source (CSRC). - * - * @author Alex Andres - */ -public class RTCRtpContributingSource { - - /** - * Indicating the most recent time a frame from an RTP packet, originating - * from this source, was delivered to the RTCRtpReceiver's MediaStreamTrack. - */ - public final long timestamp; - - /** - * The CSRC or SSRC identifier of the contributing or synchronization - * source. - */ - public final long sourceId; - - /** - * Only present for audio receivers. This is a value between 0..1 (linear), - * where 1.0 represents 0 dBov, 0 represents silence, and 0.5 represents - * approximately 6 dBSPL change in the sound pressure level from 0 dBov. - */ - public final double audioLevel; - - /** - * The last RTP timestamp, as defined in [RFC3550] Section 5.1, of the media - * played out at timestamp. - */ - public final long rtpTimestamp; - - - /** - * Creates an instance of RTCRtpContributingSource with the specified - * contributing source information. - * - * @param timestamp The most recent time a frame from an RTP packet. - * @param sourceId The CSRC or SSRC identifier of the contributing or - * synchronization source. - * @param audioLevel The sound pressure level. Only present for audio - * receivers. - * @param rtpTimestamp The last RTP timestamp. - */ - protected RTCRtpContributingSource(long timestamp, long sourceId, - double audioLevel, long rtpTimestamp) { - this.timestamp = timestamp; - this.sourceId = sourceId; - this.audioLevel = audioLevel; - this.rtpTimestamp = rtpTimestamp; - } -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpEncodingParameters.java b/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpEncodingParameters.java deleted file mode 100644 index 4309725..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpEncodingParameters.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc; - -/** - * Describes encoding options of an {@link RTCRtpSender}. - * - * @author Alex Andres - */ -public class RTCRtpEncodingParameters { - - /** - * If unset, a value is chosen by the implementation. - *
- * Note that the chosen value is NOT returned by GetParameters, because it - * may change due to an SSRC conflict, in which case the conflict is handled - * internally without any event. Another way of looking at this is that an - * unset SSRC acts as a "wildcard" SSRC. - */ - public Long ssrc; - - /** - * Indicates that this encoding is actively being sent. Setting it to false - * causes this encoding to no longer be sent. Setting it to true causes this - * encoding to be sent. - */ - public Boolean active; - - /** - * When present, indicates the maximum bitrate that can be used to send this - * encoding. If unset, there is no maximum bitrate. - */ - public Integer maxBitrate; - - /** - * When present, indicates the minimum bitrate that can be used to send this - * encoding. If unset, there is no minimum bitrate. - */ - public Integer minBitrate; - - /** - * When present, indicates the maximum frame rate that can be used to send - * this encoding, in frames per second. - */ - public Double maxFramerate; - - /** - * Only present if the sender's kind is "video". The video's resolution will - * be scaled down in each dimension by the given value before sending. For - * example, if the value is 2.0, the video will be scaled down by a factor - * of 2 in each dimension, resulting in sending a video of one quarter the - * size. If the value is 1.0, the video will not be affected. The value must - * be greater than or equal to 1.0. By default, the sender will not apply - * any scaling - */ - public Double scaleResolutionDownBy; - - - /** - * Creates an instance of RTCRtpEncodingParameters. - */ - public RTCRtpEncodingParameters() { - active = true; - } - - @Override - public String toString() { - return "RTCRtpEncodingParameters{" + "ssrc=" + ssrc + ", active=" - + active + ", maxBitrate=" + maxBitrate + ", minBitrate=" - + minBitrate + ", maxFramerate=" + maxFramerate - + ", scaleResolutionDownBy=" + scaleResolutionDownBy + '}'; - } -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpHeaderExtensionCapability.java b/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpHeaderExtensionCapability.java deleted file mode 100644 index 3263904..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpHeaderExtensionCapability.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc; - -/** - * Describes supported RTP header extensions. - * - * @author Alex Andres - */ -public class RTCRtpHeaderExtensionCapability { - - /** - * The URI of the RTP header extension. - */ - private final String uri; - - - /** - * Creates an instance of RTCRtpHeaderExtensionCapability with the specified - * RTP header extension URI. - * - * @param uri The URI of the RTP header extension. - */ - public RTCRtpHeaderExtensionCapability(String uri) { - this.uri = uri; - } - - /** - * Returns the URI of the supported RTP header extension by the system. - * - * @return The URI of the RTP header extension. - */ - public String getUri() { - return uri; - } - - @Override - public String toString() { - return String.format("%s [uri=%s]", - RTCRtpHeaderExtensionCapability.class.getSimpleName(), uri); - } -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpHeaderExtensionParameters.java b/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpHeaderExtensionParameters.java deleted file mode 100644 index ade791a..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpHeaderExtensionParameters.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc; - -/** - * Enables an application to determine whether a header extension is configured - * for use within an RTCRtpSender or RTCRtpReceiver. - * - * @author Alex Andres - */ -public class RTCRtpHeaderExtensionParameters { - - /** - * The URI of the RTP header extension. - */ - public final String uri; - - /** - * The value put in the RTP packet to identify the header extension. - */ - public final int id; - - /** - * Whether the header extension is encrypted or not. - */ - public final boolean encrypted; - - - /** - * Creates an instance of RTCRtpHeaderExtensionParameters with the specified - * header extension parameters. - * - * @param uri The URI of the RTP header extension. - * @param id The value put in the RTP packet to identify the header - * extension. - * @param encrypted Whether the header extension is encrypted or not. - */ - public RTCRtpHeaderExtensionParameters(String uri, int id, boolean encrypted) { - this.uri = uri; - this.id = id; - this.encrypted = encrypted; - } - - @Override - public String toString() { - return String.format("%s [uri=%s, id=%s, encrypted=%s]", - RTCRtpHeaderExtensionParameters.class.getSimpleName(), uri, id, - encrypted); - } -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpParameters.java b/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpParameters.java deleted file mode 100644 index 66f10d6..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpParameters.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc; - -import java.util.List; - -/** - * Describes RTP stack settings used by both {@link RTCRtpSender}s and {@link - * RTCRtpReceiver}s. - * - * @author Alex Andres - */ -public class RTCRtpParameters { - - /** - * A list containing parameters for RTP header extensions. - */ - public List headerExtensions; - - /** - * Parameters used for RTCP. - */ - public RTCRtcpParameters rtcp; - - /** - * A list containing the media codecs that an RTCRtpSender will choose from, - * as well as entries for RTX, RED and FEC mechanisms. Corresponding to each - * media codec where retransmission via RTX is enabled, there will be an - * entry in codecs with a mimeType attribute indicating retransmission via - * "audio/rtx" or "video/rtx", and an sdpFmtpLine attribute (providing the - * "apt" and "rtx-time" parameters). - */ - public List codecs; - - - @Override - public String toString() { - return String.format("%s [headerExtensions=%s, rtcp=%s, codecs=%s]", - RTCRtpParameters.class.getSimpleName(), headerExtensions, rtcp, - codecs); - } -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpReceiver.java b/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpReceiver.java deleted file mode 100644 index 0a4754b..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpReceiver.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc; - -import java.util.List; - -import dev.onvoid.webrtc.internal.NativeObject; -import dev.onvoid.webrtc.media.MediaStreamTrack; - -/** - * The RTCRtpReceiver allows an application to inspect the receipt of a {@link - * MediaStreamTrack}. - * - * @author Alex Andres - */ -public class RTCRtpReceiver extends NativeObject { - - /** - * Constructor to be used by the native api. - */ - private RTCRtpReceiver() { - - } - - /** - * The track that is associated with this RTCRtpReceiver object. Note that - * track.stop() is final, although clones are not affected. Since - * receiver.track.stop() does not implicitly stop receiver, Receiver Reports - * continue to be sent. - * - * @return The media track associated with this receiver. - */ - public native MediaStreamTrack getTrack(); - - /** - * The transport over which media for the receiver's track is received in - * the form of RTP packets. When bundling is used, multiple RTCRtpReceivers - * will share one transport and will all receive RTP and RTCP over the same - * transport. - * - * @return The transport over which media for the receiver's track is - * received. - */ - public native RTCDtlsTransport getTransport(); - - /** - * Returns the RTCRtpReceiver's current parameters containing information - * about how the track is decoded. - * - * @return The current parameters. - */ - public native RTCRtpParameters getParameters(); - - /** - * Returns an RTCRtpContributingSource for each unique CSRC identifier - * received by this RTCRtpReceiver in the last 10 seconds, in descending - * timestamp order. - * - * @return A list of contributing sources in descending timestamp order. - */ - public native List getContributingSources(); - - /** - * Returns an RTCRtpSynchronizationSource for each unique SSRC identifier - * received by this RTCRtpReceiver in the last 10 seconds, in descending - * timestamp order. - * - * @return A list of synchronization sources in descending timestamp order. - */ - public native List getSynchronizationSources(); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpSendParameters.java b/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpSendParameters.java deleted file mode 100644 index babe19b..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpSendParameters.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc; - -import java.util.List; - -/** - * Specifies RTP and RTCP parameters for an {@link RTCRtpSender}. - * - * @author Alex Andres - */ -public class RTCRtpSendParameters extends RTCRtpParameters { - - /** - * An unique identifier for the last set of parameters applied. Ensures that - * setParameters can only be called based on a previous getParameters, and - * that there are no intervening changes. - */ - public String transactionId; - - /** - * A list containing parameters for RTP encodings of media. - */ - public List encodings; - - - @Override - public String toString() { - return String.format("%s [transactionId=%s, encodings=%s, headerExtensions=%s, rtcp=%s, codecs=%s]", - RTCRtpSendParameters.class.getSimpleName(), transactionId, - encodings, headerExtensions, rtcp, codecs); - } -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpSender.java b/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpSender.java deleted file mode 100644 index 5c053a0..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpSender.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc; - -import java.util.List; - -import dev.onvoid.webrtc.internal.NativeObject; -import dev.onvoid.webrtc.media.MediaStreamTrack; - -/** - * The RTCRtpSender allows an application to control how a given {@link - * MediaStreamTrack} is encoded and transmitted to a remote peer. When {@link - * #setParameters} is called on an RTCRtpSender, the encoding is changed - * appropriately. - * - * @author Alex Andres - */ -public class RTCRtpSender extends NativeObject { - - /** - * Constructor to be used by the native api. - */ - private RTCRtpSender() { - - } - - /** - * Returns the track that is associated with this RTCRtpSender. If track is - * ended, or if the track's output is disabled, i.e. the track is disabled - * and/or muted, the RTCRtpSender MUST send silence (audio), black frames - * (video) or a zero-information-content equivalent. In the case of video, - * the RTCRtpSender SHOULD send one black frame per second. If track is - * {@code null} then the RTCRtpSender does not send. - * - * @return The media track associated with this sender. - */ - public native MediaStreamTrack getTrack(); - - /** - * The transport over which media from the MediaStreamTrack is sent in the - * form of RTP packets. When bundling is used, multiple RTCRtpSenders will - * share one transport and will all send RTP and RTCP over the same - * transport. - * - * @return The transport over which media from the MediaStreamTrack is sent. - */ - public native RTCDtlsTransport getTransport(); - - /** - * Attempts to replace the RTCRtpSender's current track with another track - * provided (or with a null track), without renegotiation. To avoid track - * identifiers changing on the remote receiving end when a track is - * replaced, the sender MUST retain the original track identifier and stream - * associations and use these in subsequent negotiations. - * - * @param withTrack The new media track. - */ - public native void replaceTrack(MediaStreamTrack withTrack); - - /** - * Updates how track is encoded and transmitted to a remote peer. Does not - * cause SDP renegotiation and can only be used to change what the media - * stack is sending or receiving within the envelope negotiated by - * Offer/Answer. The attributes in the RTCRtpSendParameters are designed to - * not enable this, so attributes like cname that cannot be changed are - * read-only. Other things, like bitrate, are controlled using limits such - * as maxBitrate, where the user agent needs to ensure it does not exceed - * the maximum bitrate specified by maxBitrate, while at the same time - * making sure it satisfies constraints on bitrate specified in other places - * such as the SDP. - * - * @param parameters The new RTP parameters. - */ - public native void setParameters(RTCRtpSendParameters parameters); - - /** - * Returns the RTCRtpSender's current parameters for how track is encoded - * and transmitted to a remote RTCRtpReceiver. - * - * @return The current RTP parameters. - */ - public native RTCRtpSendParameters getParameters(); - - /** - * Sets the IDs of the media streams associated with this sender's track. - * - * @param streamIds The IDs of the media streams. - */ - public native void setStreams(List streamIds); - - /** - * Returns the RTCDtmfSender associated with this RTCRtpSender. The RTCDtmfSender - * enables the transmission of DTMF (Dual-Tone Multi-Frequency) tones over the - * RTCPeerConnection. - * - * @return The DTMF sender object associated with this RTP sender, or null if DTMF - * is not supported for the media type of the associated track. - */ - public native RTCDtmfSender getDtmfSender(); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpSynchronizationSource.java b/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpSynchronizationSource.java deleted file mode 100644 index bdfff67..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpSynchronizationSource.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc; - -/** - * Contains information about a given synchronization source (SSRC). - * - * @author Alex Andres - */ -public class RTCRtpSynchronizationSource extends RTCRtpContributingSource { - - /** - * Only present for audio receivers. Whether the last RTP packet, delivered - * from this source, contains voice activity (true) or not (false). If the - * RFC 6464 extension header was not present, or if the peer has signaled - * that it is not using the V bit by setting the "vad" extension attribute - * to "off". - */ - public final boolean voiceActivityFlag; - - - /** - * Creates an instance of RTCRtpSynchronizationSource with the specified - * synchronization source information. - * - * @param timestamp The most recent time a frame from an RTP - * packet. - * @param source The CSRC or SSRC identifier of the contributing - * or synchronization source. - * @param audioLevel The sound pressure level. Only present for audio - * receivers. - * @param rtpTimestamp The last RTP timestamp. - * @param voiceActivityFlag Whether the last RTP packet contains voice - * activity (true) or not (false). - */ - protected RTCRtpSynchronizationSource(long timestamp, long source, - double audioLevel, long rtpTimestamp, boolean voiceActivityFlag) { - super(timestamp, source, audioLevel, rtpTimestamp); - - this.voiceActivityFlag = voiceActivityFlag; - } -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpTransceiver.java b/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpTransceiver.java deleted file mode 100644 index 6f2b040..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpTransceiver.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc; - -import dev.onvoid.webrtc.internal.NativeObject; - -import java.util.List; - -/** - * Represents a combination of an {@link RTCRtpSender} and an {@link - * RTCRtpReceiver} that share a common media ID (mid). - * - * @author Alex Andres - */ -public class RTCRtpTransceiver extends NativeObject { - - /** - * Constructor to be used by the native api. - */ - private RTCRtpTransceiver() { - - } - - /** - * The mid attribute is the mid negotiated and present in the local and - * remote descriptions. Before negotiation is complete, the mid value may be - * null. After rollbacks, the value may change from a non-null value to - * null. - * - * @return The media stream identification associated with local and remote - * descriptions. - */ - public native String getMid(); - - /** - * The RTCRtpSender corresponding to the RTP media that may be sent with mid - * = mid. - * - * @return The RTP sender associated with this transceiver. - */ - public native RTCRtpSender getSender(); - - /** - * The RTCRtpReceiver corresponding to the RTP media that may be received - * with mid = mid. - * - * @return The RTP receiver associated with this transceiver. - */ - public native RTCRtpReceiver getReceiver(); - - /** - * Indicates the preferred direction of this transceiver, which will be used - * in calls to createOffer and createAnswer. - * - * @return The preferred direction of this transceiver. - */ - public native RTCRtpTransceiverDirection getDirection(); - - /** - * Sets the preferred direction of this transceiver. An update of - * directionality does not take effect immediately. Instead, future calls to - * createOffer and createAnswer mark the corresponding media description as - * SendRecv, SendOnly, RecvOnly or Inactive. - * - * @param direction The new transceiver direction. - */ - public native void setDirection(RTCRtpTransceiverDirection direction); - - /** - * Indicates the current direction negotiated for this transceiver. The - * value of currentDirection is independent of the value of - * RTCRtpEncodingParameters.active since one cannot be deduced from the - * other. If this transceiver has never been represented in an offer/answer - * exchange, or if the transceiver is stopped, the value is null. - * - * @return The current direction negotiated for this transceiver. - */ - public native RTCRtpTransceiverDirection getCurrentDirection(); - - /** - * Irreversibly stops the RTCRtpTransceiver. The sender of this transceiver - * will no longer send, the receiver will no longer receive. Calling stop() - * updates the negotiation-needed flag for the RTCRtpTransceiver's - * associated RTCPeerConnection. Stopping a transceiver will cause future - * calls to createOffer or createAnswer to generate a zero port in the media - * description for the corresponding transceiver. - */ - public native void stop(); - - /** - * Indicates that the sender of this transceiver will no longer send, and - * that the receiver will no longer receive. It is true if either stop has - * been called or if setting the local or remote description has caused the - * RTCRtpTransceiver to be stopped. - * - * @return true if the transceiver has been stopped, false otherwise. - */ - public native boolean stopped(); - - /** - * Returns the default codec preferences used by WebRTC for this - * transceiver. - * - * @return The default codec preferences. - */ - public native List getCodecPreferences(); - - /** - * Overrides the default codec preferences used by WebRTC for this - * transceiver. When generating a session description using either {@code - * RTCPeerConnection.createOffer} or {@code RTCPeerConnection.createAnswer}, - * the RTCPeerConnection will use the indicated codecs, in the order - * specified in the provided preferences. - *

- * This method allows applications to disable the negotiation of specific - * codecs (including RTX/RED/FEC). It also allows an application to cause a - * remote peer to prefer the codec that appears first in the list for - * sending. - *

- * Setting codecs to an empty sequence resets codec preferences to any - * default value. - * - * @param preferences The preferred codec preferences. - */ - public native void setCodecPreferences( - List preferences); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpTransceiverDirection.java b/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpTransceiverDirection.java deleted file mode 100644 index 8a4cd1a..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpTransceiverDirection.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc; - -/** - * Indicates the RTCRtpTransceiver's preferred directionality. - * - * @author Alex Andres - */ -public enum RTCRtpTransceiverDirection { - - /** - * The RTCRtpTransceiver's RTCRtpSender will offer to send RTP, and will - * send RTP if the remote peer accepts and sender.getParameters().encodings[i].active - * is true for any value of i. - *

- * The RTCRtpTransceiver's RTCRtpReceiver will offer to receive RTP, and - * will receive RTP if the remote peer accepts. - */ - SEND_RECV, - - /** - * The RTCRtpTransceiver's RTCRtpSender sender will offer to send RTP, and - * will send RTP if the remote peer accepts and sender.getParameters().encodings[i].active - * is true for any value of i. - *

- * The RTCRtpTransceiver's RTCRtpReceiver will not offer to receive RTP, and - * will not receive RTP. - */ - SEND_ONLY, - - /** - * The RTCRtpTransceiver's RTCRtpSender will not offer to send RTP, and will - * not send RTP. - *

- * The RTCRtpTransceiver's RTCRtpReceiver will offer to receive RTP, and - * will receive RTP if the remote peer accepts. - */ - RECV_ONLY, - - /** - * The RTCRtpTransceiver's RTCRtpSender will not offer to send RTP, and will - * not send RTP. - *

- * The RTCRtpTransceiver's RTCRtpReceiver will not offer to receive RTP, and - * will not receive RTP. - */ - INACTIVE, - - /** - * The RTCRtpTransceiver will neither send nor receive RTP. It will generate - * a zero port in the offer. In answers, its RTCRtpSender will not offer to - * send RTP, and its RTCRtpReceiver will not offer to receive RTP. This is a - * terminal state. - */ - STOPPED; - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpTransceiverInit.java b/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpTransceiverInit.java deleted file mode 100644 index 0eb54c6..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtpTransceiverInit.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc; - -import java.util.ArrayList; -import java.util.List; - -/** - * Provides configuration options for {@link RTCRtpTransceiver}s. - * - * @see RTCPeerConnection#addTransceiver - * - * @author Alex Andres - */ -public class RTCRtpTransceiverInit { - - /** - * The direction of the RTCRtpTransceiver. - */ - public RTCRtpTransceiverDirection direction; - - /** - * Media stream ids associated with the transceiver. - */ - public List streamIds; - - /** - * Parameters for sending RTP encodings of media. - */ - public List sendEncodings; - - - /** - * Creates an instance of RTCRtpTransceiverInit. - */ - public RTCRtpTransceiverInit() { - direction = RTCRtpTransceiverDirection.SEND_RECV; - streamIds = new ArrayList<>(); - sendEncodings = new ArrayList<>(); - } - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/AudioDeviceDirectionType.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/AudioDeviceDirectionType.java deleted file mode 100644 index 1338624..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/AudioDeviceDirectionType.java +++ /dev/null @@ -1,7 +0,0 @@ -package dev.onvoid.webrtc.media; - -public enum AudioDeviceDirectionType { - UNKNOWN, - CAPTURE, - RENDER -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/Device.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/Device.java deleted file mode 100644 index e31c0ed..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/Device.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media; - -import java.util.Objects; - -public abstract class Device { - - private final String descriptor; - - private final String name; - - private DeviceTransport deviceTransport = DeviceTransport.UNKNOWN; - - private DeviceFormFactor deviceFormFactor = DeviceFormFactor.UNKNOWN; - - protected Device(String name, String descriptor) { - this.name = name; - this.descriptor = descriptor; - } - - public String getDescriptor() { - return descriptor; - } - - public String getName() { - return name; - } - - public DeviceTransport getDeviceTransport() { - return deviceTransport; - } - - public DeviceFormFactor getDeviceFormFactor() { - return deviceFormFactor; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Device device = (Device) o; - - return Objects.equals(descriptor, device.descriptor) && - Objects.equals(name, device.name); - } - - @Override - public int hashCode() { - return Objects.hash(descriptor, name); - } - - @Override - public String toString() { - return String.format("%s [name=%s, descriptor=%s, transport=%s, formFactor=%s]", - Device.class.getSimpleName(), name, descriptor, deviceTransport, deviceFormFactor); - } -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/DeviceChangeListener.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/DeviceChangeListener.java deleted file mode 100644 index 63c0abd..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/DeviceChangeListener.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media; - -/** - * A device change listener is notified whenever a media device such as a - * camera, microphone, or speaker is connected to or removed from the system. - * - * @author Alex Andres - */ -public interface DeviceChangeListener { - - /** - * A media device has been connected to the system. - * - * @param device The connected device. - */ - void deviceConnected(Device device); - - /** - * A media device has been disconnected from the system. - * - * @param device The disconnected device. - */ - void deviceDisconnected(Device device); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/DeviceFormFactor.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/DeviceFormFactor.java deleted file mode 100644 index 5783b7c..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/DeviceFormFactor.java +++ /dev/null @@ -1,9 +0,0 @@ -package dev.onvoid.webrtc.media; - -public enum DeviceFormFactor { - UNKNOWN, - SPEAKER, - MICROPHONE, - HEADSET, - HEADPHONE; -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/DeviceTransport.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/DeviceTransport.java deleted file mode 100644 index fa31c86..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/DeviceTransport.java +++ /dev/null @@ -1,8 +0,0 @@ -package dev.onvoid.webrtc.media; - -public enum DeviceTransport { - UNKNOWN, - HDMI, - USB, - WIRELESS; -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/FourCC.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/FourCC.java deleted file mode 100644 index 92f83b5..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/FourCC.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media; - -/** - * "Four character code" (4CC) enumeration mainly used for conversion. - * - * @author Alex Andres - */ -public enum FourCC { - - // Primary RGB formats - - /** Uncompressed 32-bit ARGB */ - ARGB("ARGB"), - /** Uncompressed 32-bit BGRA */ - BGRA("BGRA"), - /** Uncompressed 32-bit ABGR */ - ABGR("ABGR"), - /** Uncompressed 32-bit RGBA */ - RGBA("RGBA"), - /** Uncompressed 24-bit BGR */ - BG24("24BG"), - - // Primary YUV formats - - /** Planar 4:2:0 YUV */ - I420("I420"), - /** Planar 4:2:0 YUV with interleaved VU plane */ - NV21("NV21"), - /** Planar 4:2:0 YUV with interleaved UV plane */ - NV12("NV12"), - /** Packed 4:2:2 YUV */ - YUY2("YUY2"), - /** Packed 4:2:2 YUV */ - UYVY("UYVY"); - - - /** - * Integer FourCC value. - */ - private final int value; - - - private FourCC(String fourCC) { - int val = 0; - - for (int i = 0; i < 4; i++) { - val <<= 8; - val |= fourCC.charAt(3 - i); - } - - this.value = val; - } - - /** - * Return the FourCC as integer value. - * - * @return FourCC integer. - */ - public int value() { - return value; - } - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/MediaDevices.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/MediaDevices.java deleted file mode 100644 index ce36177..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/MediaDevices.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media; - -import dev.onvoid.webrtc.internal.NativeLoader; -import dev.onvoid.webrtc.media.audio.AudioDevice; -import dev.onvoid.webrtc.media.video.VideoCaptureCapability; -import dev.onvoid.webrtc.media.video.VideoDevice; - -import java.util.List; - -public class MediaDevices { - - static { - try { - NativeLoader.loadLibrary("webrtc-java"); - } - catch (Exception e) { - throw new RuntimeException("Load library 'webrtc-java' failed", e); - } - } - - - public static native void addDeviceChangeListener(DeviceChangeListener listener); - - public static native void removeDeviceChangeListener(DeviceChangeListener listener); - - public static native AudioDevice getDefaultAudioRenderDevice(); - - public static native AudioDevice getDefaultAudioCaptureDevice(); - - public static native List getAudioRenderDevices(); - - public static native List getAudioCaptureDevices(); - - public static native List getVideoCaptureDevices(); - - public static native List getVideoCaptureCapabilities(VideoDevice device); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/MediaSource.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/MediaSource.java deleted file mode 100644 index 325528d..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/MediaSource.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media; - -import dev.onvoid.webrtc.internal.NativeObject; - -/** - * Base class for sources. A MediaStreamTrack has an underlying source that - * provides media. A source can be shared by multiple tracks. - * - * @author Alex Andres - */ -public abstract class MediaSource extends NativeObject { - - public enum State { - - INITIALIZING, - - LIVE, - - ENDED, - - MUTED; - - } - - public native State getState(); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/MediaStream.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/MediaStream.java deleted file mode 100644 index 6904392..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/MediaStream.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media; - -import dev.onvoid.webrtc.internal.DisposableNativeObject; -import dev.onvoid.webrtc.media.audio.AudioTrack; -import dev.onvoid.webrtc.media.video.VideoTrack; - -/** - * A MediaStream is used to group several MediaStreamTrack objects into one unit - * that can be recorded or rendered. Each MediaStream can contain zero or more - * MediaStreamTrack objects. - * - * @link https://www.w3.org/TR/mediacapture-streams/#mediastream - */ -public class MediaStream extends DisposableNativeObject { - - private MediaStream() { - - } - - /** - * Returns the media stream ID which was initialized when the object was - * created. - * - * @return The media stream ID. - */ - public native String id(); - - /** - * Returns an array of MediaStreamTrack objects representing the audio - * tracks in this stream. - * - * @return The audio tracks in this stream. - */ - public native AudioTrack[] getAudioTracks(); - - /** - * Returns an array of MediaStreamTrack objects representing the video - * tracks in this stream. - * - * @return The video tracks in this stream. - */ - public native VideoTrack[] getVideoTracks(); - - /** - * Adds the given MediaStreamTrack to this MediaStream. - * - * @param track The track to add. - */ - public native void addTrack(MediaStreamTrack track); - - /** - * Removes the given MediaStreamTrack object from this MediaStream. - * - * @param track The track to remove. - */ - public native void removeTrack(MediaStreamTrack track); - - @Override - public native void dispose(); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/MediaStreamTrack.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/MediaStreamTrack.java deleted file mode 100644 index c174783..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/MediaStreamTrack.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media; - -import dev.onvoid.webrtc.internal.DisposableNativeObject; - -/** - * The MediaStreamTrack represents media of a single type that originates from - * one media source, e.g., video produced by a web camera. - * - * @link ... - * - * @author Alex Andres - */ -public abstract class MediaStreamTrack extends DisposableNativeObject { - - /** - * Field used to store a pointer to the native listener. Don't modify this - * value directly, or else you risk causing segfaults or memory leaks. - */ - @SuppressWarnings("unused") - private long listenerNativeHandle; - - /** - * If this object represents an audio track. - */ - public static final String AUDIO_TRACK_KIND = "audio"; - - /** - * If this object represents a video track. - */ - public static final String VIDEO_TRACK_KIND = "video"; - - - protected MediaStreamTrack() { - - } - - /** - * Add a listener to observe the mute condition of this track. - * - * @param listener The listener to add. - */ - public void addTrackMuteListener(MediaStreamTrackMuteListener listener) { - addMuteEventListener(listener); - } - - /** - * Remove a listener that observes the mute condition of this track. - * - * @param listener The listener to remove. - */ - public void removeTrackMuteListener(MediaStreamTrackMuteListener listener) { - removeMuteEventListener(listener); - } - - /** - * Add a listener to get notified when this track ends. - * - * @param listener The listener to add. - */ - public void addTrackEndedListener(MediaStreamTrackEndedListener listener) { - addEndedEventListener(listener); - } - - /** - * Remove a listener that gets notified when this track ends. - * - * @param listener The listener to remove. - */ - public void removeTrackEndedListener(MediaStreamTrackEndedListener listener) { - removeEndedEventListener(listener); - } - - @Override - public native void dispose(); - - /** - * Returns the string "audio" if this object represents an audio track or - * "video" if this object represents a video track. - * - * @return "audio" if this object is an audio track or "video" if this - * object is a video track. - */ - public native String getKind(); - - /** - * When a MediaStreamTrack is created, the application must generate an - * identifier string. It must initialize the object's id attribute to that - * string, unless the object is created as part of a special purpose - * algorithm that specifies how the stream id must be initialized. - * - * @return The identifier string of this track. - */ - public native String getId(); - - /** - * Indicates if this media track is enabled or not. - * - * @return true if enabled, false otherwise. - */ - public native boolean isEnabled(); - - /** - * Controls the enabled state for the media track. A disabled track will - * produce silence (if audio) or black frames (if video). After a - * MediaStreamTrack has ended, its enabled attribute still changes value - * when set; it just doesn't do anything with that new value. - * - * @param enable The new value. - */ - public native void setEnabled(boolean enable); - - /** - * Represents the state of the media track. A track will never be live again - * after becoming ended. - * - * @return The current media track state. - */ - public native MediaStreamTrackState getState(); - - private native void addEndedEventListener(MediaStreamTrackEndedListener listener); - private native void removeEndedEventListener(MediaStreamTrackEndedListener listener); - - private native void addMuteEventListener(MediaStreamTrackMuteListener listener); - private native void removeMuteEventListener(MediaStreamTrackMuteListener listener); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/MediaStreamTrackEndedListener.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/MediaStreamTrackEndedListener.java deleted file mode 100644 index e578040..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/MediaStreamTrackEndedListener.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2022 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media; - -/** - * This listener gets notified whenever a track, on which this listener is - * registered, ends. - * - * @author Alex Andres - */ -@FunctionalInterface -public interface MediaStreamTrackEndedListener { - - /** - * The given track ended. - * - * @param track The ended track. - */ - void onTrackEnd(MediaStreamTrack track); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/MediaStreamTrackMuteListener.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/MediaStreamTrackMuteListener.java deleted file mode 100644 index 0267039..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/MediaStreamTrackMuteListener.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2022 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media; - -/** - * A 'mute' condition change listener is notified whenever a media track has - * been (un)muted. - * - * @author Alex Andres - */ -@FunctionalInterface -public interface MediaStreamTrackMuteListener { - - /** - * The 'mute' condition has changed for the given track. - * - * @param track The track that has been (un)muted. - * @param muted True if the track has been muted. - */ - void onTrackMute(MediaStreamTrack track, boolean muted); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/MediaStreamTrackState.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/MediaStreamTrackState.java deleted file mode 100644 index 153f1ec..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/MediaStreamTrackState.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media; - -public enum MediaStreamTrackState { - - /** - * The track is active (the track's underlying media source is making a - * best-effort attempt to provide data in real time). The output of a track - * in the live state can be switched on and off. - */ - LIVE, - - /** - * The track has ended (the track's underlying media source is no longer - * providing data, and will never provide more data for this track). Once a - * track enters this state, it never exits it. - */ - ENDED; - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/MediaType.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/MediaType.java deleted file mode 100644 index 96185f4..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/MediaType.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media; - -public enum MediaType { - - /** - * Represents an audio media type. - */ - AUDIO, - - /** - * Represents a video media type. - */ - VIDEO, - - /** - * Represents a data media type. - */ - DATA - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/SyncClock.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/SyncClock.java deleted file mode 100644 index 790c1d4..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/SyncClock.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media; - -import dev.onvoid.webrtc.internal.NativeObject; - -/** - * Synchronized Clock for A/V timing. Provides timing functionality for - * audio and video synchronization. - * - * @author Alex Andres - */ -public class SyncClock extends NativeObject { - - /** - * Constructs a new SyncClock instance. - */ - public SyncClock() { - super(); - - initialize(); - } - - /** - * Get the current timestamp in microseconds. - * - * @return The current timestamp in microseconds. - */ - public native long getTimestampUs(); - - /** - * Get the current timestamp in milliseconds. - * - * @return The current timestamp in milliseconds. - */ - public native long getTimestampMs(); - - /** - * Get NTP timestamp for RTP synchronization. - * - * @return The NTP timestamp. - */ - public native long getNtpTime(); - - /** - * Disposes of any native resources held by this clock. - * This method should be called when the clock is no longer needed - * to prevent memory leaks. - */ - public native void dispose(); - - /** - * Initializes the native resources required by this clock. - */ - private native void initialize(); - -} \ No newline at end of file diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioConverter.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioConverter.java deleted file mode 100644 index 95080e6..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioConverter.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -import dev.onvoid.webrtc.internal.DisposableNativeObject; - -/** - * Audio format converter to remix and resample audio input data. This converter - * operates on audio frames of 10 milliseconds. Each sample is assumed to be a - * 16-bit PCM sample. - * - * @author Alex Andres - */ -public class AudioConverter extends DisposableNativeObject { - - /** The number of samples in a 10 ms frame for the input audio. */ - private final int srcSamples; - - /** The number of samples in a 10 ms frame for the output audio. */ - private final int dstSamples; - - /** The number of output samples after conversion in a 10 ms frame. */ - private final int dstSamplesOut; - - - /** - * Creates a new {@code AudioConverter} with specified sampling frequency - * and channel parameters. - * - * @param srcSampleRate The sampling frequency of the input signal. - * @param srcChannels The number of audio channels of the input signal. - * @param dstSampleRate The sampling frequency of the output signal. - * @param dstChannels The number of audio channels of the output signal. - */ - public AudioConverter(int srcSampleRate, int srcChannels, int dstSampleRate, - int dstChannels) { - this.srcSamples = srcSampleRate / 100 * srcChannels; - this.dstSamples = dstSampleRate / 100 * dstChannels; - this.dstSamplesOut = (dstSampleRate / 100) * dstChannels; - - initialize(srcSampleRate, srcChannels, dstSampleRate, dstChannels); - } - - /** - * Calculates the buffer size in bytes for the destination buffer used in - * {@link #convert}. - * - * @return The target buffer size in bytes. - */ - public int getTargetBufferSize() { - return dstSamples * 2; - } - - /** - * Converts the input samples into the output sample buffer with the - * sampling frequency and channel layout specified in the constructor. The - * audio input must be of the length of 10 milliseconds. Accordingly, the - * output has the same length of 10 milliseconds. - * - * @param src The audio samples to convert. - * @param dst The output buffer for converted audio samples. - * - * @return The number of converted samples. - * - * @throws IllegalArgumentException if the buffer sizes do not match the - * frame sizes. - */ - public int convert(byte[] src, byte[] dst) { - if (src.length / 2 < srcSamples) { - throw new IllegalArgumentException(String.format( - "Insufficient samples input length: %d vs. %d", - src.length / 2, srcSamples)); - } - if (dst.length / 2 < dstSamples) { - throw new IllegalArgumentException(String.format( - "Insufficient samples output length: %d vs. %d", - dst.length / 2, dstSamples)); - } - - convertInternal(src, srcSamples, dst, dstSamples); - - return dstSamplesOut; - } - - @Override - public native void dispose(); - - private native void initialize(int srcSampleRate, int srcChannels, int dstSampleRate, int dstChannels); - - public native void convertInternal(byte[] src, int nSrcSamples, byte[] dst, int nDstSamples); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioDevice.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioDevice.java deleted file mode 100644 index c2a5335..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioDevice.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -import dev.onvoid.webrtc.media.AudioDeviceDirectionType; -import dev.onvoid.webrtc.media.Device; - -public class AudioDevice extends Device { - - private AudioDeviceDirectionType directionType = AudioDeviceDirectionType.UNKNOWN; - - - protected AudioDevice(String name, String descriptor) { - super(name, descriptor); - } - - public AudioDeviceDirectionType getDirectionType() { - return directionType; - } -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioDeviceModule.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioDeviceModule.java deleted file mode 100644 index 3c16fee..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioDeviceModule.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -/** - * Audio device module that handles audio I/O operations. Extends the base functionality - * provided by AudioDeviceModuleBase. - * - * @author Alex Andres - */ -public class AudioDeviceModule extends AudioDeviceModuleBase { - - /** - * Constructs a new AudioDeviceModule with the platform default audio layer. - */ - public AudioDeviceModule() { - initialize(AudioLayer.kPlatformDefaultAudio); - } - - /** - * Constructs a new AudioDeviceModule with the specified audio layer. - * - * @param audioLayer The audio layer to use for this device module. - */ - public AudioDeviceModule(AudioLayer audioLayer) { - initialize(audioLayer); - } - - /** - * Initializes the native audio device with the specified audio layer. - * - * @param audioLayer The audio layer to initialize. - */ - private native void initialize(AudioLayer audioLayer); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioDeviceModuleBase.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioDeviceModuleBase.java deleted file mode 100644 index fd6f281..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioDeviceModuleBase.java +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -import static java.util.Objects.nonNull; -import static java.util.Objects.requireNonNull; - -import java.util.AbstractMap.SimpleEntry; -import java.util.List; -import java.util.Map; - -import dev.onvoid.webrtc.internal.DisposableNativeObject; -import dev.onvoid.webrtc.internal.NativeLoader; - -/** - * Base implementation for audio device modules that provides access to the system's audio devices. - *

- * This class provides functionality to list, select, and control audio input and output - * devices through the native WebRTC implementation. It manages both recording (microphone) and - * playback (speaker) devices, allowing for volume control, muting, and device selection. - *

- * It loads the required native library "webrtc-java" for accessing the underlying WebRTC functionality. - *

- * This class extends {@link DisposableNativeObject} to properly manage the lifecycle of native resources. - * - * @author Alex Andres - */ -public class AudioDeviceModuleBase extends DisposableNativeObject { - - static { - try { - NativeLoader.loadLibrary("webrtc-java"); - } - catch (Exception e) { - throw new RuntimeException("Load library 'webrtc-java' failed", e); - } - } - - - /** - * Stores the audio sinks and its corresponding native handle. - * This is used to manage the lifecycle of native resources associated with the sink. - */ - private Map.Entry sinkEntry; - - /** - * Stores the audio sources and its corresponding native handle. - * This is used to manage the lifecycle of native resources associated with the source. - */ - private Map.Entry sourceEntry; - - - @Override - public void dispose() { - if (nonNull(sinkEntry)) { - removeSinkInternal(sinkEntry.getValue()); - } - if (nonNull(sourceEntry)) { - removeSourceInternal(sourceEntry.getValue()); - } - - sinkEntry = null; - sourceEntry = null; - - disposeInternal(); - } - - /** - * Sets the audio sink for this audio device module. If a sink was previously set, it will - * be removed and replaced with the new sink. If the provided sink is the same as the - * current one, this method returns without making any changes. - * - * @param sink the audio sink to set. - * - * @throws NullPointerException if the provided sink is null. - */ - public void setAudioSink(AudioSink sink) { - requireNonNull(sink); - - if (nonNull(sinkEntry)) { - if (sink.equals(sinkEntry.getKey())) { - return; - } - - removeSinkInternal(sinkEntry.getValue()); - } - - final long nativeSink = addSinkInternal(sink); - - sinkEntry = new SimpleEntry<>(sink, nativeSink); - } - - /** - * Sets the audio source for this audio device module. If a source was previously set, it - * will be removed and replaced with the new source. If the provided source is the same as - * the current one, this method returns without making any changes. - * - * @param source the audio source to set. - * - * @throws NullPointerException if the provided source is null. - */ - public void setAudioSource(AudioSource source) { - requireNonNull(source); - - if (nonNull(sourceEntry)) { - if (source.equals(sourceEntry.getKey())) { - return; - } - - removeSourceInternal(sourceEntry.getValue()); - } - - final long nativeSource = addSourceInternal(source); - - sourceEntry = new SimpleEntry<>(source, nativeSource); - } - - /** - * Initializes the audio playout components and resources. This should be called before - * starting playback. - */ - public native void initPlayout(); - - /** - * Stops audio playback and releases associated resources. - */ - public native void stopPlayout(); - - /** - * Starts audio playback after initialization. Must be called after {@link #initPlayout()}. - */ - public native void startPlayout(); - - /** - * Initializes the audio recording components and resources. This should be called before - * starting recording. - */ - public native void initRecording(); - - /** - * Stops audio recording and releases associated resources. - */ - public native void stopRecording(); - - /** - * Starts audio recording after initialization. Must be called after {@link #initRecording()}. - */ - public native void startRecording(); - - /** - * Gets a list of available audio devices for playback. - * - * @return List of available audio playback devices. - */ - public native List getPlayoutDevices(); - - /** - * Gets a list of available audio devices for recording. - * - * @return List of available audio recording devices. - */ - public native List getRecordingDevices(); - - /** - * Sets the audio device to use for playback. - * - * @param device The audio device to use for playback. - * - * @throws NullPointerException if the device is null. - */ - public native void setPlayoutDevice(AudioDevice device); - - /** - * Sets the audio device to use for recording. - * - * @param device The audio device to use for recording. - * - * @throws NullPointerException if the device is null. - */ - public native void setRecordingDevice(AudioDevice device); - - /** - * Checks if the speaker is currently muted. - * - * @return true if the speaker is muted. - */ - public native boolean isSpeakerMuted(); - - /** - * Checks if the microphone is currently muted. - * - * @return true if the microphone is muted. - */ - public native boolean isMicrophoneMuted(); - - /** - * Gets the current speaker volume level. - * - * @return the current speaker volume level. - */ - public native int getSpeakerVolume(); - - /** - * Gets the maximum possible speaker volume level. - * - * @return the maximum speaker volume level. - */ - public native int getMaxSpeakerVolume(); - - /** - * Gets the minimum possible speaker volume level. - * - * @return the minimum speaker volume level. - */ - public native int getMinSpeakerVolume(); - - /** - * Gets the current microphone volume level. - * - * @return the current microphone volume level. - */ - public native int getMicrophoneVolume(); - - /** - * Gets the maximum possible microphone volume level. - * - * @return the maximum microphone volume level. - */ - public native int getMaxMicrophoneVolume(); - - /** - * Gets the minimum possible microphone volume level. - * - * @return the minimum microphone volume level. - */ - public native int getMinMicrophoneVolume(); - - /** - * Sets the speaker volume to the specified level. - * - * @param volume the volume level to set for the speaker. - */ - public native void setSpeakerVolume(int volume); - - /** - * Mutes or unmutes the speaker. - * - * @param mute true to mute the speaker, false to unmute. - */ - public native void setSpeakerMute(boolean mute); - - /** - * Sets the microphone volume to the specified level. - * - * @param volume the volume level to set for the microphone. - */ - public native void setMicrophoneVolume(int volume); - - /** - * Mutes or unmutes the microphone. - * - * @param mute true to mute the microphone, false to unmute. - */ - public native void setMicrophoneMute(boolean mute); - - /** - * Disposes native resources associated with this audio device module. - * Called by the public {@link #dispose()} method. - */ - private native void disposeInternal(); - - /** - * Adds an audio sink to the native layer and returns a handle to it. - * - * @param sink the audio sink to be added to the native layer. - * - * @return the native handle for the added sink. - */ - private native long addSinkInternal(AudioSink sink); - - /** - * Removes an audio sink from the native layer using its handle. - * - * @param sinkHandle the native handle of the sink to remove. - */ - private native void removeSinkInternal(long sinkHandle); - - /** - * Adds an audio source to the native layer and returns a handle to it. - * - * @param source the audio source to be added to the native layer. - * - * @return the native handle for the added source. - */ - private native long addSourceInternal(AudioSource source); - - /** - * Removes an audio source from the native layer using its handle. - * - * @param sourceHandle the native handle of the source to remove. - */ - private native void removeSourceInternal(long sourceHandle); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioLayer.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioLayer.java deleted file mode 100644 index 4ec08e6..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioLayer.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -/** - * Enumeration of available audio layer implementations across different platforms. - * This enum defines the various audio backends that can be used for audio input/output - * operations in WebRTC across different operating systems. - * - * @author Rafael Berne - */ -public enum AudioLayer { - - /** Default audio layer based on the current platform. */ - kPlatformDefaultAudio, - - /** Windows Core Audio implementation. */ - kWindowsCoreAudio, - - /** Windows Core Audio 2 implementation (newer version). */ - kWindowsCoreAudio2, - - /** Linux Advanced Linux Sound Architecture (ALSA) implementation. */ - kLinuxAlsaAudio, - - /** Linux PulseAudio implementation. */ - kLinuxPulseAudio, - - /** Android Java audio implementation using AudioRecord/AudioTrack. */ - kAndroidJavaAudio, - - /** Android OpenSL ES audio implementation. */ - kAndroidOpenSLESAudio, - - /** Android hybrid implementation with Java input and OpenSL ES output. */ - kAndroidJavaInputAndOpenSLESOutputAudio, - - /** Android AAudio implementation (introduced in Android 8.0). */ - kAndroidAAudioAudio, - - /** Android hybrid implementation with Java input and AAudio output. */ - kAndroidJavaInputAndAAudioOutputAudio, - - /** Dummy audio implementation for testing or non-audio scenarios. */ - kDummyAudio - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioOptions.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioOptions.java deleted file mode 100644 index 3e840ae..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioOptions.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -/** - * Audio options to control AudioTracks. - * - * @link Media Capture and Streams - * - * @author Alex Andres - */ -public class AudioOptions { - - /** - * When one or more audio streams are being played in the processes of - * various microphones, it is often desirable to attempt to remove the sound - * being played from the input signals recorded by the microphones. This is - * referred to as echo cancellation. There are cases where it is unnecessary, - * and it is desirable to turn it off so that no audio artifacts are - * introduced. This allows applications to control this behavior. - */ - public boolean echoCancellation; - - /** - * Automatic gain control is often desirable on the input signal recorded by - * the microphone. There are cases where it is unnecessary, and it is - * desirable to turn it off so that the audio is not altered. This allows - * applications to control this behavior. - */ - public boolean autoGainControl; - - /** - * Noise suppression is often desirable on the input signal recorded by the - * microphone. There are cases where it is unnecessary, and it is desirable to - * turn it off so that the audio is not altered. This allows applications to - * control this behavior. - */ - public boolean noiseSuppression; - - /** - * Audio processing to remove background noise of lower frequencies. - */ - public boolean highpassFilter; - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioPlayer.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioPlayer.java deleted file mode 100644 index 6ee2100..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioPlayer.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * High-level wrapper to control audio playout. Provides idempotent start/stop semantics - * around an underlying AudioDeviceModule. - * - * @author Alex Andres - */ -public class AudioPlayer { - - /** - * Indicates if the player is currently started. Used atomically to provide - * a thread-safe idempotent start/stop sequence. - */ - private final AtomicBoolean playing; - - /** - * Underlying audio device module managing the native playout resources. - * Created lazily on {@link #start()} and disposed on {@link #stop()}. - */ - private AudioDeviceModule module; - - /** - * The audio output device to use for playout. Should be set before calling {@link #start()}. - */ - private AudioDevice device; - - /** - * The audio source providing audio frames to be rendered by the device. - */ - private AudioSource source; - - - /** - * Creates a new AudioPlayer instance in a non-playing state. - */ - public AudioPlayer() { - playing = new AtomicBoolean(); - } - - /** - * Assigns the audio output device. - * - * @param device the target playout device (may be null to clear). - */ - public void setAudioDevice(AudioDevice device) { - this.device = device; - } - - /** - * Assigns the audio source supplying audio data. - * - * @param source the audio source (may be null to clear). - */ - public void setAudioSource(AudioSource source) { - this.source = source; - } - - /** - * Starts audio playout if not already running. This method is idempotent; subsequent - * calls while already playing have no effect. - *

- * Initializes and configures the underlying {@link AudioDeviceModule}. - */ - public void start() { - if (playing.compareAndSet(false, true)) { - module = new AudioDeviceModule(); - module.setPlayoutDevice(device); - module.setAudioSource(source); - module.initPlayout(); - module.startPlayout(); - } - } - - /** - * Stops audio playout if currently running and releases underlying resources. - * This method is idempotent; calling when already stopped has no effect. - */ - public void stop() { - if (playing.compareAndSet(true, false)) { - module.stopPlayout(); - module.dispose(); - } - } -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioProcessing.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioProcessing.java deleted file mode 100644 index 91a0eb6..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioProcessing.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -import dev.onvoid.webrtc.internal.DisposableNativeObject; -import dev.onvoid.webrtc.internal.NativeLoader; - -/** - * AudioProcessing provides a collection of voice processing components designed - * for real-time communications software. Accepts only linear PCM audio in - * chunks of 10 milliseconds. - * - * @author Alex Andres - */ -public class AudioProcessing extends DisposableNativeObject { - - static { - try { - NativeLoader.loadLibrary("webrtc-java"); - } - catch (Exception e) { - throw new RuntimeException("Load library 'webrtc-java' failed", e); - } - } - - - /** Cached statistics object to avoid recreation. */ - private final AudioProcessingStats stats = new AudioProcessingStats(); - - - /** - * Creates a new instance of {@code AudioProcessing}. Make sure to call - * {@link #dispose()} to release resources when finished processing. - */ - public AudioProcessing() { - initialize(); - } - - /** - * Get the audio processing statistics. - * - * @return The audio processing statistics. - */ - public AudioProcessingStats getStatistics() { - updateStats(); - - return stats; - } - - /** - * Calculates the buffer size in bytes for the destination buffer used in - * {@link #processStream} and {@link #processReverseStream}. - * - * @param inputConfig The config that describes the audio input format. - * @param outputConfig The config that describes the desired audio output - * format. - * - * @return The target buffer size in bytes. - */ - public int getTargetBufferSize(AudioProcessingStreamConfig inputConfig, - AudioProcessingStreamConfig outputConfig) { - int nSamplesIn = inputConfig.sampleRate / 100; - int nSamplesOut = outputConfig.sampleRate / 100; - - return Math.max(nSamplesIn, nSamplesOut) * outputConfig.channels * 2; - } - - /** - * Set the {@link AudioProcessingConfig} to enable/disable processing - * effects. Should be called prior processing, during processing may cause - * undesired effects and affect the audio quality. - * - * @param config The config to setup audio processing. - */ - public native void applyConfig(AudioProcessingConfig config); - - /** - * This must be called if and only if echo processing is enabled. - *

- * Sets the delay in milliseconds between {@link #processReverseStream} - * receiving a far-end frame and {@link #processStream} receiving a near-end - * frame containing the corresponding echo. - *

- * On the client-side this can be expressed as {@code delay = (t_render - - * t_analyze) + (t_process - t_capture)}. - *

- * where, - *

- * - t_analyze is the time a frame is passed to {@link - * #processReverseStream} and t_render is the time the first sample of the - * same frame is rendered by the audio hardware. - *

- * - t_capture is the time the first sample of a frame is captured by the - * audio hardware and t_process is the time the same frame is passed to - * {@link #processStream}. - * - * @param delay The new stream delay in milliseconds. - */ - public native void setStreamDelayMs(int delay); - - /** - * This must be called if and only if echo processing is enabled. - * - * @return The stream delay in milliseconds. - * - * @see #setStreamDelayMs(int) - */ - public native int getStreamDelayMs(); - - /** - * Accepts and produces a 10 ms frame interleaved 16-bit PCM audio as - * specified in {@code inputConfig} and {@code outputConfig}. {@code src} - * and {@code dest} may use the same memory, if desired. - * - * @param src The input audio samples to process. - * @param inputConfig The config that describes the audio input format. - * @param outputConfig The config that describes the desired audio output - * format. - * @param dest The target buffer for processed audio samples. - * - * @return The success/error code. 0 if processed successfully. - */ - public native int processStream(byte[] src, - AudioProcessingStreamConfig inputConfig, - AudioProcessingStreamConfig outputConfig, byte[] dest); - - /** - * Accepts and produces a 10 ms frame of interleaved 16-bit PCM audio for - * the reverse direction audio stream as specified in {@code inputConfig} - * and {@code outputConfig}. {@code src} and {@code dest} may use the same - * memory, if desired. - * - * @param src The input audio samples to process. - * @param inputConfig The config that describes the audio input format. - * @param outputConfig The config that describes the desired audio output - * format. - * @param dest The target buffer for processed audio samples. - * - * @return The success/error code. 0 if processed successfully. - */ - public native int processReverseStream(byte[] src, - AudioProcessingStreamConfig inputConfig, - AudioProcessingStreamConfig outputConfig, byte[] dest); - - @Override - public native void dispose(); - - private native void initialize(); - - private native void updateStats(); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioProcessingConfig.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioProcessingConfig.java deleted file mode 100644 index da90149..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioProcessingConfig.java +++ /dev/null @@ -1,513 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -/** - * This config is intended to be used during setup of {@link AudioProcessing} to - * enable/disable audio processing effects. - * - * @author Alex Andres - */ -public class AudioProcessingConfig { - - /** - * Configuration for the audio processing pipeline, including settings for - * downmixing and processing rates. - */ - public final Pipeline pipeline = new Pipeline(); - - /** - * Echo cancellation configuration to remove acoustic echo from capture signals. - * Controls whether echo cancellation is enabled and its filtering behavior. - */ - public final EchoCanceller echoCanceller = new EchoCanceller(); - - /** - * Legacy Gain Controller 1 (AGC1) configuration. This is the classic AGC used - * by WebRTC with optional limiter. If enabled, AGC1 will run alongside other - * modules as configured. If not set, defaults are used by the native side. - */ - public final GainController gainController = new GainController(); - - /** - * Digital gain control configuration for automatic volume adjustment. - * Automatic Gain Control (AGC) sub-module which replaces the Legacy Gain Controller 1 - * (AGC1). Includes both fixed and adaptive digital gain control settings. - */ - public final GainControllerDigital gainControllerDigital = new GainControllerDigital(); - - /** - * High-pass filter configuration for removing low-frequency components from the - * processed audio signal. - */ - public final HighPassFilter highPassFilter = new HighPassFilter(); - - /** - * Noise suppression configuration for reducing background noise in captured audio. - * Supports multiple suppression levels. - */ - public final NoiseSuppression noiseSuppression = new NoiseSuppression(); - - /** - * Capture level adjustment configuration to enable platform-driven capture - * level corrections in the APM when available. - */ - public final CaptureLevelAdjustment captureLevelAdjustment = new CaptureLevelAdjustment(); - - - /** - * Configures the audio processing pipeline settings. - */ - public static class Pipeline { - - /** - * Specifies the method to use when downmixing multiple audio channels. - * This determines how channels are combined when reducing the number of channels. - */ - public enum DownmixMethod { - /** Average across channels. */ - AverageChannels, - /** Use the first channel. */ - UseFirstChannel - } - - /** - * Maximum allowed processing rate used internally. - * May only be set to 32000 or 48000, and any differing values will be treated as 48000. - */ - int maximumInternalProcessingRate = 48000; - - /** - * When enabled, audio rendering can process multiple channels. - * Default is false. - */ - boolean multiChannelRender = false; - - /** - * When enabled, allows multi-channel processing of capture audio when AEC3 is active - * or a custom AEC is injected. - * Default is false. - */ - boolean multiChannelCapture = false; - - /** - * Determines how multiple capture channels are combined when a single-channel - * signal is required. - * Defaults to averaging all available channels. - */ - DownmixMethod captureDownmixMethod = DownmixMethod.AverageChannels; - } - - - /** - * Configuration for the echo cancellation module in audio processing. - * Controls whether echo cancellation is enabled and its filtering behavior. - */ - public static class EchoCanceller { - - /** - * Determines whether echo cancellation is enabled. - * When true, acoustic echo will be removed from the capture signal. - */ - public boolean enabled; - - /** - * Controls whether to enforce high-pass filtering with echo cancellation. - * When true, additional filtering is applied to improve echo cancellation. - * Default is true. - */ - public boolean enforceHighPassFiltering = true; - - } - - - /** - * Configuration for digital gain control in audio processing. - * Provides settings for both fixed and adaptive digital gain control. - */ - public static class GainControllerDigital { - - /** - * Adjusts the input volume applied when the audio is captured. - * This is a pre-amplifier stage before any digital gain control is applied. - */ - public static class InputVolumeController { - - /** - * Determines whether the input volume controller is enabled. - * When true, the input volume will be automatically adjusted. - */ - public boolean enabled = false; - - } - - /** - * Configuration for fixed digital gain control. - * Applies a constant gain value to the audio signal. - */ - public static class FixedDigital { - - /** - * The fixed gain to apply to the audio signal in decibels. - * The default value is 0.0 dB (no gain). - */ - public float gainDb = 0.0f; - - } - - /** - * Configuration for adaptive digital gain control. - * Automatically adjusts gain based on input signal characteristics. - */ - public static class AdaptiveDigital { - - /** - * Determines whether adaptive digital gain control is enabled. - */ - public boolean enabled; - - /** - * Headroom in decibels to maintain above the signal level. - * The default value is 5.0 dB. - */ - public float headroomDb = 5.0f; - - /** - * Maximum gain in decibels that can be applied to the signal. - * The default value is 50.0 dB. - */ - public float maxGainDb = 50.0f; - - /** - * Initial gain in decibels to apply when processing starts. - * The default value is 15.0 dB. - */ - public float initialGainDb = 15.0f; - - /** - * The maximum rate at which gain can change, in decibels per second. - * Controls how quickly the gain adapts to changing conditions. - * The default value is 6.0 dB/s. - */ - public float maxGainChangeDbPerSecond = 6.0f; - - /** - * Maximum allowable noise level in the output, in decibels relative to full scale. - * The default value is -50.0 dBFS. - */ - public float maxOutputNoiseLevelDbfs = -50.0f; - - } - - /** - * Fixed digital gain control settings. - */ - public final FixedDigital fixedDigital = new FixedDigital(); - - /** - * Adaptive digital gain control settings. - */ - public final AdaptiveDigital adaptiveDigital = new AdaptiveDigital(); - - /** - * Input volume controller settings. - */ - public final InputVolumeController inputVolumeController = new InputVolumeController(); - - /** - * Determines whether digital gain control is enabled. - */ - public boolean enabled; - - } - - - /** - * Configuration for classic Gain Controller 1 (AGC1). - * Provides simple controls commonly exposed for AGC1. - */ - public static class GainController { - - /** - * AGC1 mode selection. - */ - public enum Mode { - /** - * Adjusts the analog microphone level using hardware/OS controls to reach the target. - * Prefer this when the capture device gain can be modified without adding digital noise. - * This will require the coupling between the OS mixer controls and AGC through the - * stream_analog_level() functions. - */ - AdaptiveAnalog, - - /** - * Adjusts the signal level in the digital processing pipeline (software gain/compression). - * Use when analog control is unavailable or insufficient. - */ - AdaptiveDigital, - - /** - * Applies a constant digital gain (non-adaptive). Suitable for stable, well-calibrated inputs. - * This mode is preferred on embedded devices where the capture signal level is predictable so - * that a known gain can be applied. - */ - FixedDigital - } - - /** - * Determines whether AGC1 is enabled. - */ - public boolean enabled; - - /** - * Target level in dBFS that AGC1 aims for. Common default is 3 dB. - */ - public int targetLevelDbfs = 3; - - /** - * Compression gain in dB. Common default is 9 dB. - */ - public int compressionGainDb = 9; - - /** - * Enables the limiter to avoid clipping at the output. Default true. - */ - public boolean enableLimiter = true; - - /** - * Selected mode. Default matches native default kAdaptiveAnalog. - */ - public Mode mode = Mode.AdaptiveAnalog; - - /** - * Analog gain controller sub-config. - */ - public final AnalogGainController analogGainController = new AnalogGainController(); - - - public static class AnalogGainController { - - /** - * Enables the analog gain controller stage. - * When false, the analog (and coupled digital adaptive) logic is skipped. - */ - public boolean enabled = true; - - /** - * Deprecated upstream (kept for compatibility). Historical lower bound for the - * initial microphone volume. Has no effect in newer pipelines. - */ - public int startupMinVolume = 0; // deprecated upstream but retained for compatibility - - /** - * Minimum microphone level allowed after clipping mitigation logic adjusts gain. - */ - public int clippedLevelMin = 70; - - /** - * Enables the digital adaptive component that further refines gain after analog changes. - */ - public boolean enableDigitalAdaptive = true; - - /** - * Step size (in discrete volume units) to reduce the level when clipping is detected. - */ - public int clippedLevelStep = 15; - - /** - * Ratio threshold (0..1) of clipped samples in a window that triggers a gain reduction. - */ - public float clippedRatioThreshold = 0.1f; - - /** - * Number of frames to wait after a clipping event before applying another step change. - */ - public int clippedWaitFrames = 300; - - /** - * Predictor that anticipates clipping and adjusts gain preemptively. - */ - public static class ClippingPredictor { - - /** - * Available prediction modes describing how clipping is estimated. - */ - public enum Mode { - /** Reacts to observed clipping events only. */ - ClippingEventPrediction, - /** Adapts step size based on predicted peak evolution. */ - AdaptiveStepClippingPeakPrediction, - /** Uses a fixed step size for peak prediction adjustments. */ - FixedStepClippingPeakPrediction - } - - /** - * Enables the clipping prediction feature. - */ - public boolean enabled = false; - - /** - * Prediction mode governing the algorithm behavior. - */ - public Mode mode = Mode.ClippingEventPrediction; - - /** - * Sliding window length (frames) used to analyze recent signal peaks. - */ - public int windowLength = 5; - - /** - * Length (frames) of the reference window for comparative peak analysis. - */ - public int referenceWindowLength = 5; - - /** - * Delay (frames) applied to the reference window to form a historical baseline. - */ - public int referenceWindowDelay = 5; - - /** - * Threshold (dBFS) above which samples are considered clipped; -1.0f means auto. - */ - public float clippingThreshold = -1.0f; - - /** - * Margin (dB) added to the estimated crest factor to decide preemptive gain changes. - */ - public float crestFactorMargin = 3.0f; - - /** - * When true, uses the predicted step size; otherwise a default/fixed step is used. - */ - public boolean usePredictedStep = true; - } - - /** - * Instance holding the clipping prediction configuration. - */ - public final ClippingPredictor clippingPredictor = new ClippingPredictor(); - } - } - - - /** - * Configuration for capture level adjustment in audio processing. When enabled, the - * audio processing module may apply platform-informed adjustments to the capture level - * to improve overall gain staging. - */ - public static class CaptureLevelAdjustment { - - /** - * Indicates whether capture level adjustment is enabled. - */ - public boolean enabled; - - /** - * Scales the signal before any processing is done. Default 1.0. - */ - public float preGainFactor = 1.0f; - - /** - * Scales the signal after all processing is done. Default 1.0. - */ - public float postGainFactor = 1.0f; - - /** Emulates analog mic gain behavior when enabled. */ - public static class AnalogMicGainEmulation { - /** Enable the analog mic gain emulation. */ - public boolean enabled = false; - /** Initial analog level [0..255]. Default 255. */ - public int initialLevel = 255; - } - - /** - * Configuration for analog mic gain emulation. - */ - public final AnalogMicGainEmulation analogMicGainEmulation = new AnalogMicGainEmulation(); - } - - - /** - * Configuration for the high-pass filter in audio processing. - */ - public static class HighPassFilter { - - /** - * Determines whether the high-pass filter is enabled. - * When true, low-frequency components will be filtered out of the audio signal. - */ - public boolean enabled; - - /** - * Controls whether the filter is applied across the full frequency band. - * When true, the filter affects the entire frequency spectrum. - * Default is true. - */ - public boolean applyInFullBand = true; - - } - - - /** - * Configuration for audio level estimation. - * Provides settings to enable/disable the measurement of audio signal levels. - */ - public static class LevelEstimation { - - /** - * Determines whether audio level estimation is enabled. - * When true, the audio processing module will calculate and report signal levels. - */ - public boolean enabled; - - } - - - /** - * Configuration for noise suppression in audio processing. - */ - public static class NoiseSuppression { - - /** - * Defines the available intensity levels for noise suppression. - * Higher levels provide more aggressive noise reduction but may affect voice quality. - */ - public enum Level { - /** Minimal noise suppression, preserves most audio quality. */ - LOW, - /** Balanced noise suppression with moderate effect on audio quality. */ - MODERATE, - /** Strong noise suppression that may slightly affect voice quality. */ - HIGH, - /** Maximum noise suppression that prioritizes noise removal over voice quality. */ - VERY_HIGH - } - - /** - * Determines whether noise suppression is enabled. - * When true, background noise will be reduced in the processed audio. - */ - public boolean enabled; - - /** - * Specifies the intensity level of noise suppression to apply. - * Controls how aggressively noise is filtered from the audio signal. - */ - public Level level; - - } -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioProcessingStats.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioProcessingStats.java deleted file mode 100644 index 9bbf474..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioProcessingStats.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -/** - * This class holds various statistics related to audio processing. - * - * @author Alex Andres - */ -public class AudioProcessingStats { - - /** - * AEC Statistic: ERL = 10log_10(P_far / P_echo) - */ - public double echoReturnLoss; - - /** - * AEC Statistic: ERLE = 10log_10(P_echo / P_out) - */ - public double echoReturnLossEnhancement; - - /** - * Fraction of time that the AEC linear filter is divergent, in a 1-second - * non-overlapped aggregation window. - */ - public double divergentFilterFraction; - - /** - * The instantaneous delay estimate produced in the AEC. The unit is in - * milliseconds and the value is the instantaneous value at the time of the - * call to getStatistics(). - */ - public int delayMs; - - /** - * The delay metrics consists of the delay median and standard deviation. It - * also consists of the fraction of delay estimates that can make the echo - * cancellation perform poorly. The values are aggregated until the first - * call to getStatistics() and afterwards aggregated and updated every - * second. Note that if there are several clients pulling metrics from - * getStatistics() during a session, the first call from any of them will - * change to one-second aggregation window for all. - */ - public int delayMedianMs; - - /** - * The standard deviation of the delay, in milliseconds. - */ - public int delayStandardDeviationMs; - - /** - * Residual echo detector likelihood. - */ - public double residualEchoLikelihood; - - /** - * Maximum residual echo likelihood from the last time period. - */ - public double residualEchoLikelihoodRecentMax; - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioProcessingStreamConfig.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioProcessingStreamConfig.java deleted file mode 100644 index 5ff2e5d..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioProcessingStreamConfig.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -public class AudioProcessingStreamConfig { - - public final int sampleRate; - - public final int channels; - - - public AudioProcessingStreamConfig(int sampleRate, int channels) { - this.sampleRate = sampleRate; - this.channels = channels; - } - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioRecorder.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioRecorder.java deleted file mode 100644 index bda5ec1..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioRecorder.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * High-level recorder that captures audio from a configured {@link AudioDevice} - * and forwards frames to an {@link AudioSink}. Manages the lifecycle of the - * underlying {@link AudioDeviceModule} and offers thread-safe start/stop control. - * - * @author Alex Andres - */ -public class AudioRecorder { - - /** Indicates whether the recording is currently active (thread-safe). */ - private final AtomicBoolean capturing; - - /** Underlying audio device module handling the native capture. */ - private AudioDeviceModule module; - - /** The audio input device to record from. */ - private AudioDevice device; - - /** The sink receiving captured audio data. */ - private AudioSink sink; - - - /** - * Creates a new AudioRecorder with an inactive capture state. - */ - public AudioRecorder() { - capturing = new AtomicBoolean(); - } - - /** - * Set the audio input device to be used for recording. - * - * @param device the recording device; may be null until set. - */ - public void setAudioDevice(AudioDevice device) { - this.device = device; - } - - /** - * Set the sink that will receive captured audio frames. - * - * @param sink the audio sink implementation. - */ - public void setAudioSink(AudioSink sink) { - this.sink = sink; - } - - /** - * Start recording if not already active. Initializes and starts the underlying - * AudioDeviceModule. - */ - public void start() { - if (capturing.compareAndSet(false, true)) { - module = new AudioDeviceModule(); - module.setRecordingDevice(device); - module.setAudioSink(sink); - module.initRecording(); - module.startRecording(); - } - } - - /** - * Stop recording if active and release resources. - */ - public void stop() { - if (capturing.compareAndSet(true, false)) { - module.stopRecording(); - module.dispose(); - } - } -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioResampler.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioResampler.java deleted file mode 100644 index 192f9eb..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioResampler.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -import static java.util.Objects.requireNonNull; - -import dev.onvoid.webrtc.internal.DisposableNativeObject; - -/** - * Audio sampling rate converter. This resampler operates on audio frames of 10 - * milliseconds. Each sample is assumed to be a 16-bit PCM sample. - * - * @author Alex Andres - */ -public class AudioResampler extends DisposableNativeObject { - - /** - * Creates a new {@code AudioResampler} without sampling parameters. - */ - public AudioResampler() { - initialize(); - } - - /** - * Creates a new {@code AudioResampler} with specified sampling frequency - * parameters. - * - * @param sourceSampleRate The sampling frequency of the input signal. - * @param targetSampleRate The sampling frequency of the output signal. - * @param channels The number of audio channels to resample. - */ - public AudioResampler(int sourceSampleRate, int targetSampleRate, int channels) { - initialize(getSamplesPerChannel(sourceSampleRate), getSamplesPerChannel(targetSampleRate), channels); - } - - /** - * Converts the input samples into the output samples with the sampling - * frequency specified in the constructor. The audio input must be of the - * length of 10 milliseconds. Accordingly, the output has the length of 10 - * milliseconds. - * - * @param samplesIn The audio samples to convert. - * @param srcSamplesPerChannel The number of samples per source channel. - * @param samplesOut The converted audio samples. - * @param dstSamplesPerChannel The number of samples per destination channel. - * @param channels The number of audio channels to resample. - * - * @return The number of converted audio samples. - */ - public int resample(byte[] samplesIn, int srcSamplesPerChannel, byte[] samplesOut, int dstSamplesPerChannel, - int channels) { - requireNonNull(samplesIn); - requireNonNull(samplesOut); - - final int maxSamplesOut = samplesOut.length / 2; // 16-bit PCM sample - - if (dstSamplesPerChannel > maxSamplesOut) { - throw new IllegalArgumentException("Insufficient samples output length"); - } - - return resampleInternal(samplesIn, srcSamplesPerChannel, samplesOut, maxSamplesOut, channels); - } - - @Override - public native void dispose(); - - private native void initialize(); - - private native void initialize(int srcSamplesPerChannel, int dstSamplesPerChannel, int channels); - - private native int resampleInternal(byte[] samplesIn, int srcSamplesPerChannel, - byte[] samplesOut, int dstSamplesPerChannel, int channels); - - /** - * Returns the number of samples a buffer needs to hold for ~10ms of a single audio channel at a given sample rate. - * - * @param sampleRate The sample rate. - * - * @return The number of samples per channel. - */ - public static int getSamplesPerChannel(int sampleRate) { - return sampleRate / 100; - } -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioSink.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioSink.java deleted file mode 100644 index 7d84f0a..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioSink.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -public interface AudioSink { - - void onRecordedData(byte[] audioSamples, int nSamples, int nBytesPerSample, - int nChannels, int samplesPerSec, int totalDelayMS, int clockDrift); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioSource.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioSource.java deleted file mode 100644 index 5a7c8c7..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioSource.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -public interface AudioSource { - - int onPlaybackData(byte[] audioSamples, int nSamples, int nBytesPerSample, - int nChannels, int samplesPerSec); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioTrack.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioTrack.java deleted file mode 100644 index 78397cc..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioTrack.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -import static java.util.Objects.isNull; -import static java.util.Objects.nonNull; - -import dev.onvoid.webrtc.media.MediaStreamTrack; - -import java.util.IdentityHashMap; -import java.util.Map; - -public class AudioTrack extends MediaStreamTrack { - - private final Map sinks = new IdentityHashMap<>(); - - - private AudioTrack() { - super(); - } - - @Override - public void dispose() { - for (long nativeSink : sinks.values()) { - removeSinkInternal(nativeSink); - } - - sinks.clear(); - - super.dispose(); - } - - /** - * Adds an AudioSink to the track. A track can have any number of AudioSinks. - * - * @param sink The audio sink that will receive audio data from the track. - */ - public void addSink(AudioTrackSink sink) { - if (isNull(sink)) { - throw new NullPointerException(); - } - if (sinks.containsKey(sink)) { - return; - } - - final long nativeSink = addSinkInternal(sink); - - sinks.put(sink, nativeSink); - } - - /** - * Removes an AudioSink from the track. If the AudioSink was not attached to - * the track, this is a no-op. - */ - public void removeSink(AudioTrackSink sink) { - if (isNull(sink)) { - throw new NullPointerException(); - } - - final Long nativeSink = sinks.remove(sink); - - if (nonNull(nativeSink)) { - removeSinkInternal(nativeSink); - } - } - - /** - * Get the signal level from the audio track. - * - * @return The signal level. - */ - public native int getSignalLevel(); - - private native long addSinkInternal(AudioTrackSink sink); - - private native void removeSinkInternal(long sinkHandle); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioTrackSink.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioTrackSink.java deleted file mode 100644 index bcfc57b..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioTrackSink.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -public interface AudioTrackSink { - - void onData(byte[] data, int bitsPerSample, int sampleRate, int channels, int frames); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioTrackSource.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioTrackSource.java deleted file mode 100644 index f25ee9b..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/AudioTrackSource.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -import dev.onvoid.webrtc.media.MediaSource; - -/** - * A source for one or more AudioTracks. - * - * @author Alex Andres - */ -public class AudioTrackSource extends MediaSource { - - protected AudioTrackSource() { - - } - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/CustomAudioSource.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/CustomAudioSource.java deleted file mode 100644 index fdb3a8d..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/CustomAudioSource.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -import dev.onvoid.webrtc.media.SyncClock; - -/** - * Custom implementation of an audio source for WebRTC that allows pushing audio data - * from external sources directly to the WebRTC audio pipeline. - * - * @author Alex Andres - */ -public class CustomAudioSource extends AudioTrackSource { - - /** - * Constructs a new CustomAudioSource instance. - */ - public CustomAudioSource() { - super(); - - initialize(); - } - - /** - * Constructs a new CustomAudioSource instance with a specified SyncClock. - * - * @param clock The SyncClock to use for timing and synchronization. - */ - public CustomAudioSource(SyncClock clock) { - super(); - - initializeWithClock(clock); - } - - /** - * Pushes audio data to be processed by this audio source. - * - * @param audioData The raw audio data bytes to process. - * @param bits_per_sample The number of bits per sample (e.g., 8, 16, 32). - * @param sampleRate The sample rate of the audio in Hz (e.g., 44100, 48000). - * @param channels The number of audio channels (1 for mono, 2 for stereo). - * @param frameCount The number of frames in the provided audio data. - */ - public native void pushAudio(byte[] audioData, int bits_per_sample, - int sampleRate, int channels, int frameCount); - - /** - * Disposes of any native resources held by this audio source. - * This method should be called when the audio source is no longer needed - * to prevent memory leaks. - */ - public native void dispose(); - - /** - * Initializes the native resources required by this audio source. - */ - private native void initialize(); - - /** - * Initializes the native resources required by this audio source with a specified SyncClock. - * - * @param clock The SyncClock to use for timing and synchronization. - */ - private native void initializeWithClock(SyncClock clock); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/HeadlessAudioDeviceModule.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/HeadlessAudioDeviceModule.java deleted file mode 100644 index 28e5083..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/HeadlessAudioDeviceModule.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2025 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -/** - * Convenience AudioDeviceModule that uses the dummy audio layer. This avoids touching - * real OS audio devices while still enabling the push and pull of audio via the WebRTC - * pipeline. - * - * @author Alex Andres - */ -public class HeadlessAudioDeviceModule extends AudioDeviceModuleBase { - - /** - * Constructs a HeadlessAudioDeviceModule. - */ - public HeadlessAudioDeviceModule() { - initialize(); - } - - /** - * Initializes the native audio resources. Called during construction of the module. - */ - private native void initialize(); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/VoiceActivityDetector.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/VoiceActivityDetector.java deleted file mode 100644 index 08dfe68..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/audio/VoiceActivityDetector.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -import dev.onvoid.webrtc.internal.DisposableNativeObject; - -/** - * A voice activity detector that analyzes audio data chunks to determine the probability of voice presence in the - * audio stream. - *

- * This class provides native methods to process audio and retrieve the probability of voice activity. - * - * @author Alex Andres - */ -public class VoiceActivityDetector extends DisposableNativeObject { - - /** - * Constructs a new {@code VoiceActivityDetector} instance. - */ - public VoiceActivityDetector() { - initialize(); - } - - /** - * Processes audio data to detect voice activity. - * - * @param audio The audio data to process. - * @param samplesPerChannel The number of samples in the audio chunk. - * @param sampleRate The sample rate of the audio data in Hz. - */ - public native void process(byte[] audio, int samplesPerChannel, int sampleRate); - - /** - * Gets the probability of voice presence from the last processed audio data. - * - * @return A value between 0.0 and 1.0 representing the probability of voice presence. - */ - public native float getLastVoiceProbability(); - - /** - * Releases native resources held by this object. - */ - @Override - public native void dispose(); - - /** - * Initializes the native resources for the voice activity detector. This method is called during construction and - * sets up the underlying native implementation. - */ - private native void initialize(); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/CustomVideoSource.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/video/CustomVideoSource.java deleted file mode 100644 index 083115c..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/CustomVideoSource.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.video; - -import dev.onvoid.webrtc.media.SyncClock; - -/** - * Custom implementation of a video source for WebRTC that allows pushing video frames - * from external sources directly to the WebRTC video pipeline. - * - * @author Alex Andres - */ -public class CustomVideoSource extends VideoTrackSource { - - /** - * Constructs a new CustomVideoSource instance. - */ - public CustomVideoSource() { - super(); - - initialize(); - } - - /** - * Constructs a new CustomVideoSource instance with a specified SyncClock. - * - * @param clock The SyncClock to use for timing and synchronization. - */ - public CustomVideoSource(SyncClock clock) { - super(); - - initializeWithClock(clock); - } - - /** - * Pushes audio data to be processed by this audio source. - * - * @param frame The video frame to be pushed to the source. - */ - public native void pushFrame(VideoFrame frame); - - /** - * Disposes of any native resources held by this video source. - * This method should be called when the video source is no longer needed - * to prevent memory leaks. - */ - public native void dispose(); - - /** - * Initializes the native resources required by this video source. - */ - private native void initialize(); - - /** - * Initializes the native resources required by this video source with a specified SyncClock. - * - * @param clock The SyncClock to use for timing and synchronization. - */ - private native void initializeWithClock(SyncClock clock); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/FramePacer.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/video/FramePacer.java deleted file mode 100644 index 50b8667..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/FramePacer.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.video; - -/** - * A utility class that regulates the pace at which video frames are processed. - *

- * FramePacer ensures that frames are processed at a consistent rate by introducing - * appropriate delays between frame processing operations. This helps maintain a - * steady frame rate for video applications. - *

- * Usage example: - *

- * FramePacer pacer = new FramePacer(30); // 30 fps
- * while (processingFrames) {
- *     pacer.waitForNextFrame();
- *     // Process frame
- * }
- * 
- */ -public class FramePacer { - - /** The time interval between frames in nanoseconds. */ - private final long frameIntervalNanos; - - /** Timestamp of the last processed frame in nanoseconds. Used to calculate the appropriate delay between frames. */ - private long lastFrameTimeNanos; - - - /** - * Creates a FramePacer with the specified frame rate. - * - * @param fps Frames per second. - */ - public FramePacer(int fps) { - this.frameIntervalNanos = 1_000_000_000L / fps; // Convert to nanoseconds - this.lastFrameTimeNanos = 0; - } - - /** - * Waits for the appropriate time before the next frame should be processed. - */ - public void waitForNextFrame() { - long now = System.nanoTime(); - - if (lastFrameTimeNanos > 0) { - long elapsed = now - lastFrameTimeNanos; - - if (elapsed < frameIntervalNanos) { - long sleepTimeNanos = frameIntervalNanos - elapsed; - try { - // Convert nanoseconds to milliseconds and nanosecond remainder. - long sleepTimeMillis = sleepTimeNanos / 1_000_000; - int remainderNanos = (int) (sleepTimeNanos % 1_000_000); - - Thread.sleep(sleepTimeMillis, remainderNanos); - } - catch (InterruptedException e) { - Thread.currentThread().interrupt(); - // Return early if interrupted. - return; - } - } - } - - lastFrameTimeNanos = System.nanoTime(); - } - - public long getFrameIntervalNanos() { - return frameIntervalNanos; - } -} \ No newline at end of file diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/I420Buffer.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/video/I420Buffer.java deleted file mode 100644 index 79ae7ad..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/I420Buffer.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.video; - -import java.nio.ByteBuffer; - -public interface I420Buffer extends VideoFrameBuffer { - - /** - * Returns a direct ByteBuffer containing Y-plane data. The buffer capacity is - * at least getStrideY() * getHeight() bytes. The position of the returned - * buffer is ignored and must be 0. Callers may mutate the ByteBuffer (eg. - * through relative-read operations), so implementations must return a new - * ByteBuffer or slice for each call. - */ - ByteBuffer getDataY(); - - /** - * Returns a direct ByteBuffer containing U-plane data. The buffer capacity is - * at least getStrideU() * ((getHeight() + 1) / 2) bytes. The position of the - * returned buffer is ignored and must be 0. Callers may mutate the ByteBuffer - * (eg. through relative-read operations), so implementations must return a new - * ByteBuffer or slice for each call. - */ - ByteBuffer getDataU(); - - /** - * Returns a direct ByteBuffer containing V-plane data. The buffer capacity is - * at least getStrideV() * ((getHeight() + 1) / 2) bytes. The position of the - * returned buffer is ignored and must be 0. Callers may mutate the ByteBuffer - * (eg. through relative-read operations), so implementations must return a new - * ByteBuffer or slice for each call. - */ - ByteBuffer getDataV(); - - int getStrideY(); - - int getStrideU(); - - int getStrideV(); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/NativeI420Buffer.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/video/NativeI420Buffer.java deleted file mode 100644 index a069056..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/NativeI420Buffer.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.video; - -import dev.onvoid.webrtc.internal.RefCountedObject; - -import java.nio.ByteBuffer; - -/** - * This class wraps the native WebRTC I420BufferInterface. - */ -public class NativeI420Buffer extends RefCountedObject implements I420Buffer { - - private final ByteBuffer dataY; - private final ByteBuffer dataU; - private final ByteBuffer dataV; - - private final int strideY; - private final int strideU; - private final int strideV; - - private final int width; - private final int height; - - - private NativeI420Buffer(int width, int height, ByteBuffer dataY, int strideY, ByteBuffer dataU, int strideU, - ByteBuffer dataV, int strideV) { - this.width = width; - this.height = height; - this.dataY = dataY; - this.strideY = strideY; - this.dataU = dataU; - this.strideU = strideU; - this.dataV = dataV; - this.strideV = strideV; - } - - @Override - public ByteBuffer getDataY() { - // Return a slice to prevent relative reads from changing the position. - return dataY.slice(); - } - - @Override - public ByteBuffer getDataU() { - // Return a slice to prevent relative reads from changing the position. - return dataU.slice(); - } - - @Override - public ByteBuffer getDataV() { - // Return a slice to prevent relative reads from changing the position. - return dataV.slice(); - } - - @Override - public int getStrideY() { - return strideY; - } - - @Override - public int getStrideU() { - return strideU; - } - - @Override - public int getStrideV() { - return strideV; - } - - @Override - public int getWidth() { - return width; - } - - @Override - public int getHeight() { - return height; - } - - @Override - public I420Buffer toI420() { - return this; - } - - @Override - public VideoFrameBuffer cropAndScale(int cropX, int cropY, int cropWidth, int cropHeight, - int scaleWidth, int scaleHeight) { - return cropAndScale(this, cropX, cropY, cropWidth, cropHeight, scaleWidth, scaleHeight); - } - - @Override - public String toString() { - return String.format("%s@%d [width=%s, height=%s]", - NativeI420Buffer.class.getSimpleName(), hashCode(), - width, height); - } - - /** - * Creates a copy of this I420 buffer. This method performs a deep copy of all data in the buffer. - * - * @return A new NativeI420Buffer instance with the same dimensions and data as this buffer. - */ - public NativeI420Buffer copy() { - return copy(width, height, dataY.slice(), strideY, dataU.slice(), strideU, dataV.slice(), strideV); - } - - /** - * Allocates an empty I420Buffer suitable for an image of the given dimensions. - */ - public static native NativeI420Buffer allocate(int width, int height); - - /** - * Creates a copy of an I420 buffer with the given dimensions and data. - */ - private static native NativeI420Buffer copy(int width, int height, ByteBuffer dataY, int strideY, ByteBuffer dataU, - int strideU, ByteBuffer dataV, int strideV); - - /** - * Wraps existing ByteBuffers into NativeI420Buffer object without copying the - * contents. - */ - private static I420Buffer wrap(int width, int height, ByteBuffer dataY, int strideY, ByteBuffer dataU, - int strideU, ByteBuffer dataV, int strideV) { - if (dataY == null || dataU == null || dataV == null) { - throw new IllegalArgumentException("Data buffers cannot be null"); - } - if (!dataY.isDirect() || !dataU.isDirect() || !dataV.isDirect()) { - throw new IllegalArgumentException("Data buffers must be direct byte buffers"); - } - - // Slice the buffers to prevent external modifications to the position / limit - // of the buffer. - // Note that this doesn't protect the contents of the buffers from modifications. - dataY = dataY.slice(); - dataU = dataU.slice(); - dataV = dataV.slice(); - - final int chromaWidth = (width + 1) / 2; - final int chromaHeight = (height + 1) / 2; - - checkCapacity(dataY, width, height, strideY); - checkCapacity(dataU, chromaWidth, chromaHeight, strideU); - checkCapacity(dataV, chromaWidth, chromaHeight, strideV); - - return new NativeI420Buffer(width, height, dataY, strideY, dataU, strideU, dataV, strideV); - } - - private static VideoFrameBuffer cropAndScale(final I420Buffer buffer, int cropX, int cropY, - int cropWidth, int cropHeight, int scaleWidth, int scaleHeight) { - if (cropWidth == scaleWidth && cropHeight == scaleHeight) { - // No scaling. - ByteBuffer dataY = buffer.getDataY(); - ByteBuffer dataU = buffer.getDataU(); - ByteBuffer dataV = buffer.getDataV(); - - dataY.position(cropX + cropY * buffer.getStrideY()); - dataU.position(cropX / 2 + cropY / 2 * buffer.getStrideU()); - dataV.position(cropX / 2 + cropY / 2 * buffer.getStrideV()); - - return wrap(scaleWidth, scaleHeight, dataY.slice(), buffer.getStrideY(), dataU.slice(), - buffer.getStrideU(), dataV.slice(), buffer.getStrideV()); - } - - I420Buffer newBuffer = allocate(scaleWidth, scaleHeight); - - cropAndScale(buffer.getDataY(), buffer.getStrideY(), buffer.getDataU(), buffer.getStrideU(), - buffer.getDataV(), buffer.getStrideV(), cropX, cropY, cropWidth, cropHeight, - newBuffer.getDataY(), newBuffer.getStrideY(), newBuffer.getDataU(), newBuffer.getStrideU(), - newBuffer.getDataV(), newBuffer.getStrideV(), scaleWidth, scaleHeight); - - return newBuffer; - } - - private static void checkCapacity(ByteBuffer data, int width, int height, int stride) { - // The last row does not necessarily need padding. - final int minCapacity = stride * (height - 1) + width; - - if (data.capacity() < minCapacity) { - throw new IllegalArgumentException("Buffer must be at least " + minCapacity + - " bytes, but was " + data.capacity()); - } - } - - private static native void cropAndScale(ByteBuffer srcY, int srcStrideY, - ByteBuffer srcU, int srcStrideU, ByteBuffer srcV, int srcStrideV, int cropX, int cropY, - int cropWidth, int cropHeight, ByteBuffer dstY, int dstStrideY, ByteBuffer dstU, - int dstStrideU, ByteBuffer dstV, int dstStrideV, int scaleWidth, int scaleHeight); -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoBufferConverter.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoBufferConverter.java deleted file mode 100644 index 1b8694f..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoBufferConverter.java +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.video; - -import java.nio.ByteBuffer; - -import dev.onvoid.webrtc.media.FourCC; - -/** - * Utility methods to convert between I420 video frame buffers and other pixel - * formats represented by a FourCC. Delegates actual conversion work to native - * methods for performance. - * - * @author Alex Andres - */ -public final class VideoBufferConverter { - - /** - * Convert an arbitrary {@link VideoFrameBuffer} to the specified pixel format - * (given by {@code fourCC}) and write the result into a destination byte array. - *

- * The source buffer is first converted (if necessary) to an intermediate - * I420 layout via {@link VideoFrameBuffer#toI420()} and then transformed. - * - * @param src Source video frame buffer (will be converted to I420 if not already). - * @param dst Destination byte array expected to be large enough to hold the converted frame. - * @param fourCC Target FourCC format identifier. - * - * @throws NullPointerException if {@code src} or {@code dst} is {@code null}. - * @throws Exception if the native conversion fails. - */ - public static void convertFromI420(VideoFrameBuffer src, byte[] dst, FourCC fourCC) - throws Exception { - if (src == null) { - throw new NullPointerException("Source buffer must not be null"); - } - if (dst == null) { - throw new NullPointerException("Destination buffer must not be null"); - } - - I420Buffer i420 = src.toI420(); - - I420toByteArray( - i420.getDataY(), i420.getStrideY(), - i420.getDataU(), i420.getStrideU(), - i420.getDataV(), i420.getStrideV(), - dst, - i420.getWidth(), i420.getHeight(), - fourCC.value()); - } - - /** - * Convert an arbitrary {@link VideoFrameBuffer} to the specified pixel format - * and write the result into a {@link ByteBuffer}. If the destination buffer - * is a direct buffer, a native direct path is used; otherwise its backing - * array (or a temporary array) is employed. - * - * @param src Source video frame buffer. - * @param dst Writable destination {@link ByteBuffer}. Must not be read-only. - * @param fourCC Target FourCC format identifier. - * - * @throws NullPointerException if {@code src} or {@code dst} is {@code null}. - * @throws IllegalArgumentException if {@code dst} is read-only. - * @throws Exception if the native conversion fails. - */ - public static void convertFromI420(VideoFrameBuffer src, ByteBuffer dst, FourCC fourCC) - throws Exception { - if (src == null) { - throw new NullPointerException("Source buffer must not be null"); - } - if (dst == null) { - throw new NullPointerException("Destination buffer must not be null"); - } - if (dst.isReadOnly()) { - throw new IllegalArgumentException("Destination buffer must not be read-only"); - } - - I420Buffer i420 = src.toI420(); - - if (dst.isDirect()) { - I420toDirectBuffer( - i420.getDataY(), i420.getStrideY(), - i420.getDataU(), i420.getStrideU(), - i420.getDataV(), i420.getStrideV(), - dst, - i420.getWidth(), i420.getHeight(), - fourCC.value()); - } - else { - byte[] arrayBuffer; - - if (dst.hasArray()) { - arrayBuffer = dst.array(); - } - else { - arrayBuffer = new byte[dst.remaining()]; - dst.get(arrayBuffer); - } - - I420toByteArray( - i420.getDataY(), i420.getStrideY(), - i420.getDataU(), i420.getStrideU(), - i420.getDataV(), i420.getStrideV(), - arrayBuffer, - i420.getWidth(), i420.getHeight(), - fourCC.value()); - } - } - - /** - * Convert a source frame stored in a byte array (encoded in the format indicated - * by {@code fourCC}) to I420 and write the planes into the provided {@link I420Buffer}. - * - * @param src Source pixel data in the specified FourCC format. - * @param dst Destination I420 buffer (pre-allocated). - * @param fourCC FourCC describing the layout of {@code src}. - * - * @throws NullPointerException if {@code src} or {@code dst} is {@code null}. - * @throws Exception if the native conversion fails. - */ - public static void convertToI420(byte[] src, I420Buffer dst, FourCC fourCC) - throws Exception { - if (src == null) { - throw new NullPointerException("Source buffer must not be null"); - } - if (dst == null) { - throw new NullPointerException("Destination buffer must not be null"); - } - - byteArrayToI420( - src, - dst.getWidth(), dst.getHeight(), - dst.getDataY(), dst.getStrideY(), - dst.getDataU(), dst.getStrideU(), - dst.getDataV(), dst.getStrideV(), - fourCC.value()); - } - - /** - * Convert a source frame stored in a {@link ByteBuffer} (encoded in the format - * specified by {@code fourCC}) to I420 and write the result into the provided - * {@link I420Buffer}. Uses a direct native path for direct buffers; otherwise - * reads from the backing or a temporary array. - * - * @param src Source pixel data buffer. - * @param dst Destination I420 buffer (pre-allocated). - * @param fourCC FourCC describing the layout of {@code src}. - * - * @throws NullPointerException if {@code src} or {@code dst} is {@code null}. - * @throws Exception if the native conversion fails. - */ - public static void convertToI420(ByteBuffer src, I420Buffer dst, FourCC fourCC) - throws Exception { - if (src == null) { - throw new NullPointerException("Source buffer must not be null"); - } - if (dst == null) { - throw new NullPointerException("Destination buffer must not be null"); - } - - if (src.isDirect()) { - directBufferToI420( - src, - dst.getWidth(), dst.getHeight(), - dst.getDataY(), dst.getStrideY(), - dst.getDataU(), dst.getStrideU(), - dst.getDataV(), dst.getStrideV(), - fourCC.value()); - } - else { - byte[] arrayBuffer; - - if (src.hasArray()) { - arrayBuffer = src.array(); - } - else { - arrayBuffer = new byte[src.remaining()]; - src.get(arrayBuffer); - } - - byteArrayToI420( - arrayBuffer, - dst.getWidth(), dst.getHeight(), - dst.getDataY(), dst.getStrideY(), - dst.getDataU(), dst.getStrideU(), - dst.getDataV(), dst.getStrideV(), - fourCC.value()); - } - } - - private native static void I420toByteArray( - ByteBuffer srcY, int srcStrideY, - ByteBuffer srcU, int srcStrideU, - ByteBuffer srcV, int srcStrideV, - byte[] dst, - int width, int height, - int fourCC) throws Exception; - - private native static void I420toDirectBuffer( - ByteBuffer srcY, int srcStrideY, - ByteBuffer srcU, int srcStrideU, - ByteBuffer srcV, int srcStrideV, - ByteBuffer dst, - int width, int height, - int fourCC) throws Exception; - - private native static void byteArrayToI420( - byte[] src, - int width, int height, - ByteBuffer dstY, int dstStrideY, - ByteBuffer dstU, int dstStrideU, - ByteBuffer dstV, int dstStrideV, - int fourCC) throws Exception; - - private native static void directBufferToI420( - ByteBuffer src, - int width, int height, - ByteBuffer dstY, int dstStrideY, - ByteBuffer dstU, int dstStrideU, - ByteBuffer dstV, int dstStrideV, - int fourCC) throws Exception; - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoCapture.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoCapture.java deleted file mode 100644 index 4aadf35..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoCapture.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.video; - -import dev.onvoid.webrtc.internal.NativeObject; - -/** - * A class representing a video capture device that can be controlled to capture video. - * Extends NativeObject to interact with native code implementations. - *

- * VideoCapture capture = new VideoCapture();
- * capture.setVideoCaptureDevice(device);
- * capture.setVideoCaptureCapability(capability);
- * capture.setVideoSink(sink);
- * capture.start();
- * // ... consume frames via sink ...
- * capture.stop();
- * capture.dispose();
- * 
- * Notes: - *
  • Always call dispose() to release native resources.
  • - *
  • Methods are not guaranteed to be thread-safe unless externally synchronized.
  • - * - * @author Alex Andres - */ -public class VideoCapture extends NativeObject { - - /** - * Constructs a new VideoCapture and initializes underlying native resources. - * Initialization failures are typically surfaced as runtime exceptions - * originating from native code. - */ - public VideoCapture() { - initialize(); - } - - /** - * Selects the physical (or virtual) video input device to capture from. - *

    - * Constraints / Lifecycle: - *

  • Must be invoked before {@link #start()}.
  • - *
  • Re-setting the device after capture has started may require an - * internal restart (implementation-dependent).
  • - * - * @param device Non-null device descriptor to bind. Passing {@code null} - * is invalid and may raise a {@link NullPointerException}. - * - * @throws IllegalStateException if called after disposal. - */ - public native void setVideoCaptureDevice(VideoDevice device); - - /** - * Defines desired capture parameters (resolution, frame rate, pixel format, etc.). - *

    - * Constraints: - *

  • Should be called after selecting the device and before {@link #start()}.
  • - *
  • Some capabilities may be adjusted (e.g., negotiated to the nearest supported values).
  • - * - * @param capability Desired capture capability (must be non-null). - * - * @throws IllegalArgumentException if unsupported or invalid. - * @throws IllegalStateException if called after disposal. - */ - public native void setVideoCaptureCapability(VideoCaptureCapability capability); - - /** - * Registers (or replaces) the sink that will receive decoded/raw video frames. - *

    - * Behavior: - *

  • May be called before or after {@link #start()}.
  • - *
  • Passing {@code null} (if supported) detaches the current sink and - * frames will be dropped until a new sink is set.
  • - * - * @param sink The consumer of captured frames. - * - * @throws IllegalStateException if called after disposal. - */ - public native void setVideoSink(VideoTrackSink sink); - - /** - * Begins asynchronous frame capture and delivery to the configured sink. - *

    - * Idempotency: - * Calling start() while already started should be a no-op (implementation-dependent). - * - * @throws IllegalStateException if prerequisites (device/capability) are missing - * or the instance is disposed. - */ - public native void start(); - - /** - * Stops frame capture. - *

    - * Behavior: - *

  • Drains or discards in-flight frames (implementation-dependent).
  • - *
  • Safe to call multiple times (idempotent).
  • - * - * @throws IllegalStateException if the instance is disposed. - */ - public native void stop(); - - /** - * Releases native resources associated with this capture instance. - *

    - * Lifecycle: - *

  • Implicitly stops capture if currently running.
  • - *
  • After disposal, further method calls (other than additional dispose attempts) - * are invalid and may throw {@link IllegalStateException}.
  • - *

    - * Best Practice: - * Always invoke in a finally block or use a higher-level resource management - * construct to avoid native leaks. - */ - public native void dispose(); - - /** - * Internal native initialization hook invoked exactly once by the constructor. - * Not intended for direct external use. - *

    - * Failure Handling: - * Should raise a runtime exception if initialization fails. - */ - private native void initialize(); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoCaptureCapability.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoCaptureCapability.java deleted file mode 100644 index 9cbe7a4..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoCaptureCapability.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.video; - -import java.util.Objects; - -public class VideoCaptureCapability { - - public final int width; - - public final int height; - - public final int frameRate; - - - public VideoCaptureCapability(int width, int height, int frameRate) { - this.width = width; - this.height = height; - this.frameRate = frameRate; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - VideoCaptureCapability other = (VideoCaptureCapability) o; - - return width == other.width && height == other.height && - frameRate == other.frameRate; - } - - @Override - public int hashCode() { - return Objects.hash(width, height, frameRate); - } - - @Override - public String toString() { - return String.format("%s [width=%s, height=%s, frameRate=%s]", - VideoCaptureCapability.class.getSimpleName(), - width, height, frameRate); - } -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoDesktopSource.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoDesktopSource.java deleted file mode 100644 index 5db3bc0..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoDesktopSource.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.video; - -public class VideoDesktopSource extends VideoTrackSource { - - public VideoDesktopSource() { - super(); - - initialize(); - } - - public native void setSourceId(long sourceId, boolean isWindow); - - public native void setFrameRate(int frameRate); - - public native void setMaxFrameSize(int width, int height); - - public native void start(); - - public native void stop(); - - public native void dispose(); - - private native void initialize(); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoDevice.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoDevice.java deleted file mode 100644 index 310aa86..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoDevice.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.video; - -import dev.onvoid.webrtc.media.Device; - -public class VideoDevice extends Device { - - protected VideoDevice(String name, String descriptor) { - super(name, descriptor); - } - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoDeviceSource.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoDeviceSource.java deleted file mode 100644 index d350675..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoDeviceSource.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.video; - -public class VideoDeviceSource extends VideoTrackSource { - - public VideoDeviceSource() { - super(); - - initialize(); - } - - public native void setVideoCaptureDevice(VideoDevice device); - - public native void setVideoCaptureCapability(VideoCaptureCapability capability); - - public native void start(); - - public native void stop(); - - public native void dispose(); - - private native void initialize(); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoFrame.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoFrame.java deleted file mode 100644 index 79ec2ea..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoFrame.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.video; - -import dev.onvoid.webrtc.internal.RefCounted; - -/** - * Represents a video frame with an underlying buffer, rotation information, and timestamp. - *

    - * A VideoFrame holds reference to its buffer data and implements the RefCounted - * interface to manage the lifecycle of native resources through reference counting. - * The frame includes a timestamp in nanoseconds for synchronization purposes. - * - * @author Alex Andres - */ -public class VideoFrame implements RefCounted { - - /** The underlying frame buffer. */ - public final VideoFrameBuffer buffer; - - /** Rotation of the frame in degrees. */ - public final int rotation; - - /** Timestamp of the frame in nanoseconds. */ - public final long timestampNs; - - - /** - * Creates a new VideoFrame with the specified buffer, rotation and timestamp. - * - * @param buffer The video frame buffer containing the actual frame data. - * @param timestampNs The timestamp of the frame in nanoseconds. - * - * @throws IllegalArgumentException If buffer is null. - */ - public VideoFrame(VideoFrameBuffer buffer, long timestampNs) { - this(buffer, 0, timestampNs); - } - - /** - * Creates a new VideoFrame with the specified buffer, rotation and timestamp. - * - * @param buffer The video frame buffer containing the actual frame data. - * @param rotation The rotation of the frame in degrees (must be a multiple of 90). - * @param timestampNs The timestamp of the frame in nanoseconds. - * - * @throws IllegalArgumentException If buffer is null or rotation is not a multiple of 90. - */ - public VideoFrame(VideoFrameBuffer buffer, int rotation, long timestampNs) { - if (buffer == null) { - throw new IllegalArgumentException("VideoFrameBuffer must not be null"); - } - if (rotation % 90 != 0) { - throw new IllegalArgumentException("Rotation must be a multiple of 90"); - } - - this.buffer = buffer; - this.rotation = rotation; - this.timestampNs = timestampNs; - } - - /** - * Creates a deep copy of this VideoFrame. The new frame will have its own copy of the buffer data. - * - * @return A new VideoFrame with a copy of the buffer data. - */ - public VideoFrame copy() { - NativeI420Buffer nativeBuffer = (NativeI420Buffer) buffer; - - return new VideoFrame(nativeBuffer.copy(), rotation, timestampNs); - } - - @Override - public void retain() { - buffer.retain(); - } - - @Override - public void release() { - buffer.release(); - } - - @Override - public String toString() { - return String.format("%s@%d [buffer=%s, rotation=%s, timestampNs=%s]", - VideoFrame.class.getSimpleName(), hashCode(), - buffer, rotation, timestampNs); - } - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoFrameBuffer.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoFrameBuffer.java deleted file mode 100644 index ce327fb..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoFrameBuffer.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.video; - -import dev.onvoid.webrtc.internal.RefCounted; - -/** - * Base class for frame buffers of different types of pixel format and storage. - */ -public interface VideoFrameBuffer extends RefCounted { - - /** - * Resolution of the buffer in pixels. - */ - int getWidth(); - - int getHeight(); - - /** - * Returns a memory-backed frame in I420 format. If the pixel data is in - * another format, a conversion will take place. All implementations must - * provide a fallback to I420 for compatibility with, e.g., the internal - * WebRTC software encoders. - */ - I420Buffer toI420(); - - /** - * Crops a region defined by |cropX|, |cropY|, |cropWidth| and |cropHeight|. - * Scales it to size |scaleWidth| x |scaleHeight|. - */ - VideoFrameBuffer cropAndScale(int cropX, int cropY, int cropWidth, - int cropHeight, int scaleWidth, int scaleHeight); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoTrack.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoTrack.java deleted file mode 100644 index 85e3bcc..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoTrack.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.video; - -import static java.util.Objects.isNull; -import static java.util.Objects.nonNull; - -import dev.onvoid.webrtc.media.MediaStreamTrack; - -import java.util.IdentityHashMap; -import java.util.Map; - -public class VideoTrack extends MediaStreamTrack { - - private final Map sinks = new IdentityHashMap<>(); - - - private VideoTrack() { - super(); - } - - @Override - public void dispose() { - for (long nativeSink : sinks.values()) { - removeSinkInternal(nativeSink); - } - - sinks.clear(); - - super.dispose(); - } - - /** - * Adds a VideoSink to the track. A track can have any number of - * VideoSinks. - * - * @param sink The video sink to add. - */ - public void addSink(VideoTrackSink sink) { - if (isNull(sink)) { - throw new NullPointerException(); - } - if (sinks.containsKey(sink)) { - return; - } - - final long nativeSink = addSinkInternal(sink); - - sinks.put(sink, nativeSink); - } - - /** - * Removes a VideoSink from the track. If the VideoSink was not attached to - * the track, this is a no-op. - */ - public void removeSink(VideoTrackSink sink) { - if (isNull(sink)) { - throw new NullPointerException(); - } - - final Long nativeSink = sinks.remove(sink); - - if (nonNull(nativeSink)) { - removeSinkInternal(nativeSink); - } - } - - private native long addSinkInternal(VideoTrackSink sink); - - private native void removeSinkInternal(long sinkHandle); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoTrackSink.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoTrackSink.java deleted file mode 100644 index 69fc274..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoTrackSink.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.video; - -public interface VideoTrackSink { - - void onVideoFrame(VideoFrame frame); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoTrackSource.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoTrackSource.java deleted file mode 100644 index 5931c67..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/VideoTrackSource.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.video; - -import dev.onvoid.webrtc.media.MediaSource; - -/** - * A source for one or more VideoTracks. - */ -public class VideoTrackSource extends MediaSource { - - protected VideoTrackSource() { - - } - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/DesktopCaptureCallback.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/DesktopCaptureCallback.java deleted file mode 100644 index 4a9defd..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/DesktopCaptureCallback.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.video.desktop; - -import dev.onvoid.webrtc.media.video.VideoFrame; - -/** - * Callback interface for desktop capture operations. Implementers receive captured frames from a desktop capture - * source. - * - * @author Alex Andres - */ -public interface DesktopCaptureCallback { - - /** - * Called when a frame has been captured from the desktop. - * - * @param result The result of the capture operation. - * @param frame The captured video frame data, if successful. - */ - void onCaptureResult(DesktopCapturer.Result result, VideoFrame frame); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/DesktopCapturer.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/DesktopCapturer.java deleted file mode 100644 index 55b5239..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/DesktopCapturer.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.video.desktop; - -import dev.onvoid.webrtc.internal.DisposableNativeObject; - -import java.util.List; - -/** - * Abstract base class for desktop capture functionality. - *

    - * The DesktopCapturer provides the core functionality for capturing content from desktop sources - * like screens and windows. It leverages native implementation through JNI for efficient capture - * operations. - *

    - * This class handles source selection, configuration of capture parameters like frame rate - * and focus behavior, and the capture process itself. - *

    - * Implementations must provide the concrete native functionality for different platforms. - * - * @see ScreenCapturer - * @see WindowCapturer - * - * @author Alex Andres - */ -public abstract class DesktopCapturer extends DisposableNativeObject { - - /** - * Represents the result of a desktop capture operation. - * This enum defines possible outcomes when attempting to capture a desktop frame, - * indicating success or different types of failures that may occur during the capture process. - */ - public enum Result { - - /** - * The frame was captured successfully. - */ - SUCCESS, - - /** - * There was a temporary error. The caller should continue calling - * CaptureFrame(), in the expectation that it will eventually recover. - */ - ERROR_TEMPORARY, - - /** - * Capture has failed and will keep failing if the caller tries calling - * CaptureFrame() again. - */ - ERROR_PERMANENT, - - /** - * ERROR_PERMANENT - */ - MAX_VALUE; - } - - - /** - * The DesktopCapturer doesn't take ownership of the callback. When the - * DesktopCapturer is disposed, the callback will be disposed using this - * handle. - */ - private long callbackHandle; - - - @Override - public native void dispose(); - - /** - * Retrieves a list of available desktop sources that can be captured. - * - * @return A list of desktop sources (screens, windows). - */ - public native List getDesktopSources(); - - /** - * Selects a specific desktop source for capturing. - * - * @param source The desktop source to be captured. - */ - public native void selectSource(DesktopSource source); - - /** - * Sets whether the selected source should be focused during capture. - * - * @param focus True to focus the selected source, false otherwise. - */ - public native void setFocusSelectedSource(boolean focus); - - /** - * Sets the maximum frame rate for the desktop capture. - * - * @param maxFrameRate The maximum number of frames to capture per second. - */ - public native void setMaxFrameRate(int maxFrameRate); - - /** - * Starts the desktop capture process with the provided callback. - * - * @param callback The callback that receives capture events and frames. - */ - public native void start(DesktopCaptureCallback callback); - - /** - * Captures a single frame manually. - * The capture result will be delivered via the callback provided in {@link #start}. - */ - public native void captureFrame(); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/DesktopFrame.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/DesktopFrame.java deleted file mode 100644 index 727246b..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/DesktopFrame.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.video.desktop; - -import java.awt.Dimension; -import java.awt.Rectangle; -import java.nio.ByteBuffer; -import java.util.StringJoiner; - -/** - * Represents a desktop frame captured from a screen or window. - * - * @author Alex Andres - */ -public class DesktopFrame { - - /** The rectangle in full desktop coordinates. */ - public final Rectangle frameRect; - - /** The size of the frame in full desktop coordinate space. */ - public final Dimension frameSize; - - /** The scale factor from DIPs to physical pixels of the frame. */ - public final float scale; - - /** Distance in the buffer between two neighboring rows in bytes. */ - public final int stride; - - /** The underlying frame buffer. */ - public final ByteBuffer buffer; - - - /** - * Creates a new desktop frame with the specified properties. - * - * @param frameRect The rectangle in full desktop coordinates. - * @param frameSize The size of the frame in full desktop coordinate space. - * @param scale The scale factor from DIPs to physical pixels of the frame. - * @param stride Distance in the buffer between two neighboring rows in bytes. - * @param buffer The underlying frame buffer. - */ - public DesktopFrame(Rectangle frameRect, Dimension frameSize, float scale, int stride, ByteBuffer buffer) { - this.frameRect = frameRect; - this.frameSize = frameSize; - this.scale = scale; - this.stride = stride; - this.buffer = buffer; - } - - @Override - public String toString() { - return new StringJoiner(", ", - DesktopFrame.class.getSimpleName() + "[", "]") - .add("frameRect=" + frameRect) - .add("frameSize=" + frameSize) - .add("scale=" + scale) - .add("stride=" + stride) - .add("buffer=" + buffer) - .toString(); - } -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/DesktopSource.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/DesktopSource.java deleted file mode 100644 index f8f1b8f..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/DesktopSource.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.video.desktop; - -import java.util.Objects; - -/** - * Represents a desktop source that can be captured, such as a screen or window. - * Desktop sources are uniquely identified by their ID. - * - * @author Alex Andres - */ -public class DesktopSource { - - /** The title or name of the desktop source. */ - public final String title; - - /** The unique identifier of the desktop source. */ - public final long id; - - - /** - * Creates a new desktop source with the specified title and ID. - * - * @param title The title or name of the desktop source. - * @param id The unique identifier of the desktop source. - */ - public DesktopSource(String title, long id) { - this.title = title; - this.id = id; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - DesktopSource other = (DesktopSource) o; - - return id == other.id; - } - - @Override - public int hashCode() { - return Objects.hash(id); - } - - @Override - public String toString() { - return String.format("%s@%d [title=%s, id=%s]", - DesktopSource.class.getSimpleName(), hashCode(), title, id); - } -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/DesktopSourceType.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/DesktopSourceType.java deleted file mode 100644 index 84e2da8..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/DesktopSourceType.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.video.desktop; - -/** - * Represents the type of desktop source that can be captured for video. - * Used in desktop capture functionality to distinguish between different source types. - * - * @author Alex Andres - */ -public enum DesktopSourceType { - - /** Represents a screen/monitor desktop source. Used when capturing the entire screen or a specific monitor. */ - SCREEN, - - /** Represents a window desktop source. Used when capturing a specific application window. */ - WINDOW; - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/PowerManagement.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/PowerManagement.java deleted file mode 100644 index c416b45..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/PowerManagement.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.video.desktop; - -/** - * Power management assertions to wake the display and prevent it from going to sleep on user idle. - * - * @author Alex Andres - */ -public class PowerManagement { - - /** - * Declares that the user is active on the system and prevents the sleep idle time-out. - */ - native public void enableUserActivity(); - - /** - * Declares that the user is no longer active on the system and allow the system to idle to sleep normally. - */ - native public void disableUserActivity(); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/ScreenCapturer.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/ScreenCapturer.java deleted file mode 100644 index 76eb703..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/ScreenCapturer.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.video.desktop; - -/** - * A screen capture implementation of the DesktopCapturer. This class provides functionality to capture screen content. - * - * @author Alex Andres - */ -public class ScreenCapturer extends DesktopCapturer { - - /** - * Creates a new ScreenCapturer instance and initializes the components required for screen capturing. - */ - public ScreenCapturer() { - initialize(); - } - - /** - * Initializes the native components required for screen capturing. - */ - private native void initialize(); - -} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/WindowCapturer.java b/webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/WindowCapturer.java deleted file mode 100644 index fc61ab0..0000000 --- a/webrtc/src/main/java/dev/onvoid/webrtc/media/video/desktop/WindowCapturer.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.video.desktop; - -/** - * A capturer for individual windows on the desktop. Allows for capturing specific application windows for streaming - * or recording. - * - * @author Alex Andres - */ -public class WindowCapturer extends DesktopCapturer { - - /** - * Constructs a new WindowCapturer instance and initializes the components required for window capturing. - */ - public WindowCapturer() { - initialize(); - } - - /** - * Initializes the native implementation of the window capturer. - */ - private native void initialize(); - -} diff --git a/webrtc/src/main/java/module-info.java b/webrtc/src/main/java/module-info.java index 6af2184..9f74839 100644 --- a/webrtc/src/main/java/module-info.java +++ b/webrtc/src/main/java/module-info.java @@ -4,9 +4,5 @@ exports dev.onvoid.webrtc; exports dev.onvoid.webrtc.logging; - exports dev.onvoid.webrtc.media; - exports dev.onvoid.webrtc.media.audio; - exports dev.onvoid.webrtc.media.video; - exports dev.onvoid.webrtc.media.video.desktop; - + } \ No newline at end of file diff --git a/webrtc/src/main/resources/META-INF/native-image/jni-config.json b/webrtc/src/main/resources/META-INF/native-image/jni-config.json index 56ce019..bef170f 100644 --- a/webrtc/src/main/resources/META-INF/native-image/jni-config.json +++ b/webrtc/src/main/resources/META-INF/native-image/jni-config.json @@ -67,22 +67,6 @@ "name":"dev.onvoid.webrtc.RTCRtcpMuxPolicy", "methods":[{"name":"values","parameterTypes":[] }] }, - { - "name":"dev.onvoid.webrtc.RTCRtpReceiver", - "methods":[{"name":"","parameterTypes":[] }] - }, - { - "name":"dev.onvoid.webrtc.RTCRtpSender", - "methods":[{"name":"","parameterTypes":[] }] - }, - { - "name":"dev.onvoid.webrtc.RTCRtpTransceiver", - "methods":[{"name":"","parameterTypes":[] }] - }, - { - "name":"dev.onvoid.webrtc.RTCRtpTransceiverDirection", - "methods":[{"name":"values","parameterTypes":[] }] - }, { "name":"dev.onvoid.webrtc.RTCSdpType", "methods":[{"name":"values","parameterTypes":[] }] @@ -106,56 +90,5 @@ { "name":"dev.onvoid.webrtc.logging.Logging$Severity", "methods":[{"name":"values","parameterTypes":[] }] - }, - { - "name":"dev.onvoid.webrtc.media.Device", - "fields":[ - {"name":"descriptor"}, - {"name":"name"} - ] - }, - { - "name":"dev.onvoid.webrtc.media.MediaSource$State", - "methods":[{"name":"values","parameterTypes":[] }] - }, - { - "name":"dev.onvoid.webrtc.media.MediaStream", - "methods":[{"name":"","parameterTypes":[] }] - }, - { - "name":"dev.onvoid.webrtc.media.MediaStreamTrackState", - "methods":[{"name":"values","parameterTypes":[] }] - }, - { - "name":"dev.onvoid.webrtc.media.MediaType", - "methods":[{"name":"values","parameterTypes":[] }] - }, - { - "name":"dev.onvoid.webrtc.media.audio.AudioDevice", - "methods":[{"name":"","parameterTypes":["java.lang.String","java.lang.String"] }] - }, - { - "name":"dev.onvoid.webrtc.media.audio.AudioLayer", - "methods":[{"name":"values","parameterTypes":[] }] - }, - { - "name":"dev.onvoid.webrtc.media.audio.AudioProcessingConfig$NoiseSuppression$Level", - "methods":[{"name":"values","parameterTypes":[] }] - }, - { - "name":"dev.onvoid.webrtc.media.audio.AudioTrack", - "methods":[{"name":"","parameterTypes":[] }] - }, - { - "name":"dev.onvoid.webrtc.media.audio.AudioTrackSource", - "methods":[{"name":"","parameterTypes":[] }] - }, - { - "name":"dev.onvoid.webrtc.media.video.VideoTrack", - "methods":[{"name":"","parameterTypes":[] }] - }, - { - "name":"dev.onvoid.webrtc.media.video.desktop.DesktopCapturer$Result", - "methods":[{"name":"values","parameterTypes":[] }] } ] diff --git a/webrtc/src/main/resources/META-INF/native-image/reflect-config.json b/webrtc/src/main/resources/META-INF/native-image/reflect-config.json index d555c86..d468750 100644 --- a/webrtc/src/main/resources/META-INF/native-image/reflect-config.json +++ b/webrtc/src/main/resources/META-INF/native-image/reflect-config.json @@ -44,48 +44,6 @@ { "name": "dev.onvoid.webrtc.RTCRtcpParameters" }, - { - "name": "dev.onvoid.webrtc.RTCRtpCapabilities" - }, - { - "name": "dev.onvoid.webrtc.RTCRtpCodecCapability" - }, - { - "name": "dev.onvoid.webrtc.RTCRtpCodecParameters" - }, - { - "name": "dev.onvoid.webrtc.RTCRtpContributingSource" - }, - { - "name": "dev.onvoid.webrtc.RTCRtpEncodingParameters" - }, - { - "name": "dev.onvoid.webrtc.RTCRtpHeaderExtensionCapability" - }, - { - "name": "dev.onvoid.webrtc.RTCRtpHeaderExtensionParameters" - }, - { - "name": "dev.onvoid.webrtc.RTCRtpParameters" - }, - { - "name": "dev.onvoid.webrtc.RTCRtpReceiver" - }, - { - "name": "dev.onvoid.webrtc.RTCRtpSender" - }, - { - "name": "dev.onvoid.webrtc.RTCRtpSendParameters" - }, - { - "name": "dev.onvoid.webrtc.RTCRtpSynchronizationSource" - }, - { - "name": "dev.onvoid.webrtc.RTCRtpTransceiver" - }, - { - "name": "dev.onvoid.webrtc.RTCRtpTransceiverDirection" - }, { "name": "dev.onvoid.webrtc.RTCSdpType" }, @@ -112,59 +70,5 @@ }, { "name": "dev.onvoid.webrtc.logging.LogSink" - }, - { - "name": "dev.onvoid.webrtc.media.audio.AudioDevice" - }, - { - "name": "dev.onvoid.webrtc.media.audio.AudioOptions" - }, - { - "name": "dev.onvoid.webrtc.media.audio.AudioProcessing" - }, - { - "name": "dev.onvoid.webrtc.media.audio.AudioProcessingConfig" - }, - { - "name": "dev.onvoid.webrtc.media.audio.AudioProcessingStats" - }, - { - "name": "dev.onvoid.webrtc.media.audio.AudioProcessingStreamConfig" - }, - { - "name": "dev.onvoid.webrtc.media.audio.AudioSink" - }, - { - "name": "dev.onvoid.webrtc.media.audio.AudioSource" - }, - { - "name": "dev.onvoid.webrtc.media.audio.AudioTrack" - }, - { - "name": "dev.onvoid.webrtc.media.audio.AudioTrackSink" - }, - { - "name": "dev.onvoid.webrtc.media.audio.AudioTrackSource" - }, - { - "name": "dev.onvoid.webrtc.media.video.VideoCapture" - }, - { - "name": "dev.onvoid.webrtc.media.video.VideoCaptureCapability" - }, - { - "name": "dev.onvoid.webrtc.media.video.VideoDesktopSource" - }, - { - "name": "dev.onvoid.webrtc.media.video.VideoDevice" - }, - { - "name": "dev.onvoid.webrtc.media.video.desktop.DesktopCaptureCallback" - }, - { - "name": "dev.onvoid.webrtc.media.video.desktop.DesktopFrame" - }, - { - "name": "dev.onvoid.webrtc.media.video.desktop.DesktopSource" } ] diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/PeerConnectionFactoryTests.java b/webrtc/src/test/java/dev/onvoid/webrtc/PeerConnectionFactoryTests.java index 53872b5..b624db7 100644 --- a/webrtc/src/test/java/dev/onvoid/webrtc/PeerConnectionFactoryTests.java +++ b/webrtc/src/test/java/dev/onvoid/webrtc/PeerConnectionFactoryTests.java @@ -18,34 +18,10 @@ import static org.junit.jupiter.api.Assertions.*; -import dev.onvoid.webrtc.media.MediaSource; -import dev.onvoid.webrtc.media.MediaStreamTrackState; -import dev.onvoid.webrtc.media.MediaType; -import dev.onvoid.webrtc.media.audio.*; -import dev.onvoid.webrtc.media.video.VideoDeviceSource; -import dev.onvoid.webrtc.media.video.VideoTrack; - import org.junit.jupiter.api.Test; class PeerConnectionFactoryTests extends TestBase { - @Test - void createWithAudioDeviceModule() { - AudioDeviceModule audioDevModule = new AudioDeviceModule(AudioLayer.kDummyAudio); - - PeerConnectionFactory factory = new PeerConnectionFactory(audioDevModule); - factory.dispose(); - } - - @Test - void createWithAudioProcessing() { - AudioDeviceModule audioDevModule = new AudioDeviceModule(AudioLayer.kDummyAudio); - AudioProcessing audioProcessing = new AudioProcessing(); - - PeerConnectionFactory factory = new PeerConnectionFactory(audioDevModule, audioProcessing); - factory.dispose(); - } - @Test void createPeerConnectionNullParams() { assertThrows(NullPointerException.class, () -> { @@ -68,113 +44,4 @@ void createPeerConnection() { peerConnection.close(); } - - @Test - void createAudioSourceNullOptions() { - assertThrows(NullPointerException.class, () -> { - factory.createAudioSource(null); - }); - } - - @Test - void createAudioSource() { - AudioOptions audioOptions = new AudioOptions(); - AudioTrackSource audioSource = factory.createAudioSource(audioOptions); - - assertNotNull(audioSource); - assertEquals(MediaSource.State.LIVE, audioSource.getState()); - } - - @Test - void createAudioTrackNullParams() { - assertThrows(NullPointerException.class, () -> { - factory.createAudioTrack(null, null); - }); - - assertThrows(NullPointerException.class, () -> { - factory.createAudioTrack("audioTrack", null); - }); - } - - @Test - void createAudioTrack() { - AudioOptions audioOptions = new AudioOptions(); - AudioTrackSource audioSource = factory.createAudioSource(audioOptions); - AudioTrack audioTrack = factory.createAudioTrack("audioTrack", audioSource); - - assertNotNull(audioTrack); - assertEquals("audio", audioTrack.getKind()); - assertEquals("audioTrack", audioTrack.getId()); - assertEquals(MediaStreamTrackState.LIVE, audioTrack.getState()); - assertTrue(audioTrack.isEnabled()); - } - - @Test - void createVideoTrackNullParams() { - assertThrows(NullPointerException.class, () -> { - factory.createVideoTrack(null, null); - }); - - assertThrows(NullPointerException.class, () -> { - factory.createVideoTrack("videoTrack", null); - }); - } - - @Test - void createVideoTrack() { - VideoDeviceSource videoSource = new VideoDeviceSource(); - VideoTrack videoTrack = factory.createVideoTrack("videoTrack", videoSource); - - assertNotNull(videoTrack); - assertEquals("video", videoTrack.getKind()); - assertEquals("videoTrack", videoTrack.getId()); - assertEquals(MediaStreamTrackState.LIVE, videoTrack.getState()); - assertTrue(videoTrack.isEnabled()); - } - - @Test - void getReceiverCapabilities() { - RTCRtpCapabilities audioCapabilities = factory - .getRtpReceiverCapabilities(MediaType.AUDIO); - RTCRtpCapabilities videoCapabilities = factory - .getRtpReceiverCapabilities(MediaType.VIDEO); - - assertNotNull(audioCapabilities); - assertNotNull(videoCapabilities); - - assertNotNull(audioCapabilities.getCodecs()); - assertNotNull(audioCapabilities.getHeaderExtensions()); - - assertFalse(audioCapabilities.getCodecs().isEmpty()); - assertFalse(audioCapabilities.getHeaderExtensions().isEmpty()); - - assertNotNull(videoCapabilities.getCodecs()); - assertNotNull(videoCapabilities.getHeaderExtensions()); - - assertFalse(videoCapabilities.getCodecs().isEmpty()); - assertFalse(videoCapabilities.getHeaderExtensions().isEmpty()); - } - - @Test - void getSenderCapabilities() { - RTCRtpCapabilities audioCapabilities = factory - .getRtpSenderCapabilities(MediaType.AUDIO); - RTCRtpCapabilities videoCapabilities = factory - .getRtpSenderCapabilities(MediaType.VIDEO); - - assertNotNull(audioCapabilities); - assertNotNull(videoCapabilities); - - assertNotNull(audioCapabilities.getCodecs()); - assertNotNull(audioCapabilities.getHeaderExtensions()); - - assertFalse(audioCapabilities.getCodecs().isEmpty()); - assertFalse(audioCapabilities.getHeaderExtensions().isEmpty()); - - assertNotNull(videoCapabilities.getCodecs()); - assertNotNull(videoCapabilities.getHeaderExtensions()); - - assertFalse(videoCapabilities.getCodecs().isEmpty()); - assertFalse(videoCapabilities.getHeaderExtensions().isEmpty()); - } } diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/RTCDtmfSenderTests.java b/webrtc/src/test/java/dev/onvoid/webrtc/RTCDtmfSenderTests.java deleted file mode 100644 index d047a01..0000000 --- a/webrtc/src/test/java/dev/onvoid/webrtc/RTCDtmfSenderTests.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc; - -import static org.junit.jupiter.api.Assertions.*; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import dev.onvoid.webrtc.media.audio.AudioOptions; -import dev.onvoid.webrtc.media.audio.AudioTrack; -import dev.onvoid.webrtc.media.audio.AudioTrackSource; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -/** - * Unit tests for the {@link RTCDtmfSender} class. - */ -class RTCDtmfSenderTests extends TestBase { - - /** - * Test implementation of RTCDtmfSenderObserver that records tone change events. - */ - private static class TestDtmfSenderObserver implements RTCDtmfSenderObserver { - - private final List tones = new ArrayList<>(); - private final List toneBuffers = new ArrayList<>(); - private final CountDownLatch completedLatch = new CountDownLatch(1); - - - @Override - public void onToneChange(String tone, String toneBuffer) { - tones.add(tone); - toneBuffers.add(toneBuffer); - - if (tone == null || tone.isEmpty()) { - completedLatch.countDown(); - } - } - - List getTones() { - return tones; - } - - List getToneBuffers() { - return toneBuffers; - } - - void waitUntilCompleted() throws InterruptedException { - completedLatch.await(); - } - - boolean awaitCompletion() throws InterruptedException { - return completedLatch.await(1, TimeUnit.SECONDS); - } - } - - TestPeerConnection caller; - TestPeerConnection callee; - - RTCDtmfSender dtmfSender; - - - @BeforeEach - void init() throws Exception { - caller = new TestPeerConnection(factory); - callee = new TestPeerConnection(factory); - - RTCPeerConnection peerConnection = caller.getPeerConnection(); - - AudioOptions audioOptions = new AudioOptions(); - AudioTrackSource audioSource = factory.createAudioSource(audioOptions); - AudioTrack audioTrack = factory.createAudioTrack("audioTrack", audioSource); - - List streamIds = new ArrayList<>(); - streamIds.add("stream1"); - - RTCRtpSender sender = peerConnection.addTrack(audioTrack, streamIds); - dtmfSender = sender.getDtmfSender(); - - caller.setRemotePeerConnection(callee); - callee.setRemotePeerConnection(caller); - - callee.setRemoteDescription(caller.createOffer()); - caller.setRemoteDescription(callee.createAnswer()); - - caller.waitUntilConnected(); - callee.waitUntilConnected(); - } - - @AfterEach - void dispose() { - caller.close(); - callee.close(); - } - - @Test - void canInsertDtmf() { - assertNotNull(dtmfSender); - assertTrue(dtmfSender.canInsertDtmf(), "DTMF sender should be able to insert DTMF tones."); - } - - @Test - void insertDtmf() { - assertTrue(dtmfSender.insertDtmf("123", 100, 70)); - assertTrue(dtmfSender.insertDtmf("ABC", 100, 70)); - assertTrue(dtmfSender.insertDtmf("#*,", 100, 70)); - assertFalse(dtmfSender.insertDtmf("123", 30, 70)); // Duration too short - assertFalse(dtmfSender.insertDtmf("123", 100, 20)); // InterToneGap too short - } - - @Test - void getTones() throws InterruptedException { - insertTones(Arrays.asList("1", "2", "3"), 100, 70); - } - - @Test - void getDuration() throws InterruptedException { - assertEquals(100, dtmfSender.duration()); // Default value - - insertTones(Arrays.asList("1", "2", "3"), 120, 70); - assertEquals(120, dtmfSender.duration()); - - insertTones(Arrays.asList("4", "5", "6"), 170, 70); - assertEquals(170, dtmfSender.duration()); - } - - @Test - void getInterToneGap() throws InterruptedException { - assertEquals(50, dtmfSender.interToneGap()); // Default value - - insertTones(Arrays.asList("1", "2", "3"), 100, 70); - assertEquals(70, dtmfSender.interToneGap()); - - insertTones(Arrays.asList("4", "5", "6"), 100, 60); - assertEquals(60, dtmfSender.interToneGap()); - } - - @Test - void registerAndUnregisterObserver() throws InterruptedException { - TestDtmfSenderObserver observer = new TestDtmfSenderObserver(); - - dtmfSender.registerObserver(observer); - dtmfSender.insertDtmf("123", 100, 70); - - observer.waitUntilCompleted(); - - assertEquals(Arrays.asList("1", "2", "3", null), observer.getTones()); - - dtmfSender.unregisterObserver(); - dtmfSender.insertDtmf("456", 100, 70); - - Thread.sleep(500); - - assertEquals(Arrays.asList("1", "2", "3", null), observer.getTones()); // No new events - } - - private void insertTones(List tones, int duration, int interToneGap) throws InterruptedException { - TestDtmfSenderObserver observer = new TestDtmfSenderObserver(); - - dtmfSender.registerObserver(observer); - assertTrue(dtmfSender.insertDtmf(String.join("", tones), duration, interToneGap)); - - // Wait until the DTMF sequence completes (observer receives null/empty tone). - assertTrue(observer.awaitCompletion(), - "Timed out waiting for DTMF sequence to complete"); - - // All tones should have been delivered to the observer in order, followed by null. - List expectedTones = new ArrayList<>(tones); - expectedTones.add(null); - assertEquals(expectedTones, observer.getTones()); - - // After completion, the internal tone buffer should be empty. - assertNull(dtmfSender.tones()); - - dtmfSender.unregisterObserver(); - } -} diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/RTCPeerConnectionTests.java b/webrtc/src/test/java/dev/onvoid/webrtc/RTCPeerConnectionTests.java index 751ccbc..e86e529 100644 --- a/webrtc/src/test/java/dev/onvoid/webrtc/RTCPeerConnectionTests.java +++ b/webrtc/src/test/java/dev/onvoid/webrtc/RTCPeerConnectionTests.java @@ -18,12 +18,6 @@ import static org.junit.jupiter.api.Assertions.*; -import dev.onvoid.webrtc.media.audio.AudioOptions; -import dev.onvoid.webrtc.media.audio.AudioTrackSource; -import dev.onvoid.webrtc.media.audio.AudioTrack; -import dev.onvoid.webrtc.media.video.VideoDeviceSource; -import dev.onvoid.webrtc.media.video.VideoTrack; - import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; @@ -91,162 +85,6 @@ void configuration() { peerConnection.close(); } - @Test - void addTrackNullParams() { - AudioTrackSource audioSource = factory.createAudioSource(new AudioOptions()); - AudioTrack track = factory.createAudioTrack("audioTrack", audioSource); - - assertThrows(NullPointerException.class, () -> { - peerConnection.addTrack(null, null); - }); - - assertThrows(NullPointerException.class, () -> { - peerConnection.addTrack(track, null); - }); - } - - @Test - void addTrack() { - AudioTrackSource audioSource = factory.createAudioSource(new AudioOptions()); - AudioTrack audioTrack = factory.createAudioTrack("audioTrack", audioSource); - - VideoDeviceSource videoSource = new VideoDeviceSource(); - VideoTrack videoTrack = factory.createVideoTrack("videoTrack", videoSource); - - List streamIds = new ArrayList<>(); - streamIds.add("stream-0"); - - RTCRtpSender audioSender = peerConnection.addTrack(audioTrack, streamIds); - RTCRtpSender videoSender = peerConnection.addTrack(videoTrack, streamIds); - - RTCRtpSender[] senders = peerConnection.getSenders(); - RTCRtpReceiver[] receivers = peerConnection.getReceivers(); - - assertNotNull(audioSender); - assertEquals(audioTrack.getId(), audioSender.getTrack().getId()); - assertNotNull(videoSender); - assertEquals(videoTrack.getId(), videoSender.getTrack().getId()); - assertEquals(2, senders.length); - assertEquals(2, receivers.length); - } - - @Test - void removeTrack() { - AudioTrackSource audioSource = factory.createAudioSource(new AudioOptions()); - AudioTrack audioTrack = factory.createAudioTrack("audioTrack", audioSource); - - VideoDeviceSource videoSource = new VideoDeviceSource(); - VideoTrack videoTrack = factory.createVideoTrack("videoTrack", videoSource); - - List streamIds = new ArrayList<>(); - streamIds.add("stream-0"); - - RTCRtpSender audioSender = peerConnection.addTrack(audioTrack, streamIds); - RTCRtpSender videoSender = peerConnection.addTrack(videoTrack, streamIds); - - peerConnection.removeTrack(audioSender); - peerConnection.removeTrack(videoSender); - - assertEquals(2, peerConnection.getSenders().length); - } - - @Test - void addTransceiverNullParams() { - assertThrows(NullPointerException.class, () -> { - peerConnection.addTransceiver(null, null); - }); - } - - @Test - void addAudioTransceiver() { - AudioTrackSource audioSource = factory.createAudioSource(new AudioOptions()); - AudioTrack track = factory.createAudioTrack("audioTrack", audioSource); - - RTCRtpTransceiver transceiver = peerConnection.addTransceiver(track, new RTCRtpTransceiverInit()); - - assertNotNull(transceiver); - - RTCRtpTransceiver[] transceivers = peerConnection.getTransceivers(); - - assertNotNull(transceivers); - assertEquals(1, transceivers.length); - assertEquals(transceiver.getSender().getTrack().getId(), transceivers[0].getSender().getTrack().getId()); - assertEquals(RTCRtpTransceiverDirection.SEND_RECV, transceiver.getDirection()); - } - - @Test - void addSendOnlyAudioTransceiver() { - AudioTrackSource audioSource = factory.createAudioSource(new AudioOptions()); - AudioTrack track = factory.createAudioTrack("audioTrack", audioSource); - - RTCRtpTransceiverInit init = new RTCRtpTransceiverInit(); - init.direction = RTCRtpTransceiverDirection.SEND_ONLY; - - RTCRtpTransceiver transceiver = peerConnection.addTransceiver(track, init); - - assertNotNull(transceiver); - assertEquals(RTCRtpTransceiverDirection.SEND_ONLY, transceiver.getDirection()); - } - - @Test - void addRecvOnlyAudioTransceiver() { - AudioTrackSource audioSource = factory.createAudioSource(new AudioOptions()); - AudioTrack track = factory.createAudioTrack("audioTrack", audioSource); - - RTCRtpTransceiverInit init = new RTCRtpTransceiverInit(); - init.direction = RTCRtpTransceiverDirection.RECV_ONLY; - - RTCRtpTransceiver transceiver = peerConnection.addTransceiver(track, init); - - assertNotNull(transceiver); - assertEquals(RTCRtpTransceiverDirection.RECV_ONLY, transceiver.getDirection()); - } - - @Test - void addVideoTransceiver() { - VideoDeviceSource videoSource = new VideoDeviceSource(); - VideoTrack track = factory.createVideoTrack("videoTrack", videoSource); - - RTCRtpTransceiver transceiver = peerConnection.addTransceiver(track, new RTCRtpTransceiverInit()); - - assertNotNull(transceiver); - - RTCRtpTransceiver[] transceivers = peerConnection.getTransceivers(); - - assertNotNull(transceivers); - assertEquals(1, transceivers.length); - assertEquals(transceiver.getSender().getTrack().getId(), transceivers[0].getSender().getTrack().getId()); - assertEquals(RTCRtpTransceiverDirection.SEND_RECV, transceiver.getDirection()); - } - - @Test - void addSendOnlyVideoTransceiver() { - VideoDeviceSource videoSource = new VideoDeviceSource(); - VideoTrack track = factory.createVideoTrack("videoTrack", videoSource); - - RTCRtpTransceiverInit init = new RTCRtpTransceiverInit(); - init.direction = RTCRtpTransceiverDirection.SEND_ONLY; - - RTCRtpTransceiver transceiver = peerConnection.addTransceiver(track, init); - - assertNotNull(transceiver); - assertEquals(RTCRtpTransceiverDirection.SEND_ONLY, transceiver.getDirection()); - } - - @Test - void addRecvOnlyVideoTransceiver() { - VideoDeviceSource videoSource = new VideoDeviceSource(); - VideoTrack track = factory.createVideoTrack("videoTrack", videoSource); - - RTCRtpTransceiverInit init = new RTCRtpTransceiverInit(); - init.direction = RTCRtpTransceiverDirection.RECV_ONLY; - - RTCRtpTransceiver transceiver = peerConnection.addTransceiver(track, init); - - assertNotNull(transceiver); - assertEquals(RTCRtpTransceiverDirection.RECV_ONLY, transceiver.getDirection()); - } - @Test void createDataChannel() { RTCDataChannelInit options = new RTCDataChannelInit(); diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/RTCRtpTransceiverTests.java b/webrtc/src/test/java/dev/onvoid/webrtc/RTCRtpTransceiverTests.java deleted file mode 100644 index a743e5a..0000000 --- a/webrtc/src/test/java/dev/onvoid/webrtc/RTCRtpTransceiverTests.java +++ /dev/null @@ -1,61 +0,0 @@ -package dev.onvoid.webrtc; - -import dev.onvoid.webrtc.media.MediaType; -import dev.onvoid.webrtc.media.audio.AudioOptions; -import dev.onvoid.webrtc.media.audio.AudioTrackSource; -import dev.onvoid.webrtc.media.audio.AudioTrack; -import dev.onvoid.webrtc.media.video.VideoDesktopSource; -import dev.onvoid.webrtc.media.video.VideoTrack; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class RTCRtpTransceiverTests extends TestBase { - - private TestPeerConnection connection; - - - @BeforeEach - void init() { - connection = new TestPeerConnection(factory); - } - - @AfterEach - void dispose() { - connection.close(); - } - - @Test - void setCodecCapabilities() { - RTCRtpCapabilities audioCapabilities = factory - .getRtpReceiverCapabilities(MediaType.AUDIO); - RTCRtpCapabilities videoCapabilities = factory - .getRtpReceiverCapabilities(MediaType.VIDEO); - - List audioPreferences = new ArrayList<>(); - audioPreferences.add(audioCapabilities.getCodecs().get(0)); - - List videoPreferences = new ArrayList<>(); - videoPreferences.add(videoCapabilities.getCodecs().get(0)); - - AudioTrackSource audioSource = factory.createAudioSource(new AudioOptions()); - AudioTrack audioTrack = factory.createAudioTrack("audioTrack", audioSource); - - VideoDesktopSource desktopSource = new VideoDesktopSource(); - VideoTrack videoTrack = factory.createVideoTrack("videoTrack", desktopSource); - - RTCPeerConnection peerConnection = connection.getPeerConnection(); - RTCRtpTransceiver audioTransceiver = peerConnection.addTransceiver(audioTrack, - new RTCRtpTransceiverInit()); - RTCRtpTransceiver videoTransceiver = peerConnection.addTransceiver(videoTrack, - new RTCRtpTransceiverInit()); - - audioTransceiver.setCodecPreferences(audioPreferences); - videoTransceiver.setCodecPreferences(videoPreferences); - } - -} diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/TestBase.java b/webrtc/src/test/java/dev/onvoid/webrtc/TestBase.java index f313dc8..95c5960 100644 --- a/webrtc/src/test/java/dev/onvoid/webrtc/TestBase.java +++ b/webrtc/src/test/java/dev/onvoid/webrtc/TestBase.java @@ -16,9 +16,6 @@ package dev.onvoid.webrtc; -import dev.onvoid.webrtc.media.audio.AudioDeviceModule; -import dev.onvoid.webrtc.media.audio.AudioLayer; - import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.TestInstance; @@ -36,18 +33,14 @@ public abstract class TestBase { protected PeerConnectionFactory factory; - protected AudioDeviceModule audioDevModule; - @BeforeAll protected void initFactory() { - audioDevModule = new AudioDeviceModule(AudioLayer.kDummyAudio); - factory = new PeerConnectionFactory(audioDevModule); + factory = new PeerConnectionFactory(); } @AfterAll protected void disposeFactory() { - audioDevModule.dispose(); factory.dispose(); } diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/logging/LoggingTests.java b/webrtc/src/test/java/dev/onvoid/webrtc/logging/LoggingTests.java index efeb9f1..2e1a247 100644 --- a/webrtc/src/test/java/dev/onvoid/webrtc/logging/LoggingTests.java +++ b/webrtc/src/test/java/dev/onvoid/webrtc/logging/LoggingTests.java @@ -22,8 +22,6 @@ import dev.onvoid.webrtc.PeerConnectionFactory; import dev.onvoid.webrtc.logging.Logging.Severity; -import dev.onvoid.webrtc.media.audio.AudioDeviceModule; -import dev.onvoid.webrtc.media.audio.AudioLayer; import org.junit.jupiter.api.Test; @@ -42,12 +40,10 @@ void logInfo() throws Exception { Logging.addLogSink(Logging.Severity.INFO, sink); - AudioDeviceModule audioDevModule = new AudioDeviceModule(AudioLayer.kDummyAudio); - PeerConnectionFactory factory = new PeerConnectionFactory(audioDevModule); + PeerConnectionFactory factory = new PeerConnectionFactory(); latch.await(); - audioDevModule.dispose(); factory.dispose(); } diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/media/MediaSourceTests.java b/webrtc/src/test/java/dev/onvoid/webrtc/media/MediaSourceTests.java deleted file mode 100644 index 4a1a7f1..0000000 --- a/webrtc/src/test/java/dev/onvoid/webrtc/media/MediaSourceTests.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media; - -import static org.junit.jupiter.api.Assertions.*; - -import dev.onvoid.webrtc.TestBase; -import dev.onvoid.webrtc.media.audio.AudioOptions; -import dev.onvoid.webrtc.media.audio.AudioTrackSource; - -import org.junit.jupiter.api.Test; - -class MediaSourceTests extends TestBase { - - @Test - void audioSourceStateAfterCreation() { - AudioOptions audioOptions = new AudioOptions(); - AudioTrackSource audioSource = factory.createAudioSource(audioOptions); - - assertEquals(MediaSource.State.LIVE, audioSource.getState()); - } - -} diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/AudioConverterTest.java b/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/AudioConverterTest.java deleted file mode 100644 index c00e0b0..0000000 --- a/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/AudioConverterTest.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -import static org.junit.jupiter.api.Assertions.assertThrows; - -import org.junit.jupiter.api.Test; - -class AudioConverterTest { - - @Test - void downSample() { - convert(new ProcessBuffer(48000, 44100, 1, 1)); - } - - @Test - void upSample() { - convert(new ProcessBuffer(44100, 48000, 1, 1)); - } - - @Test - void downMix() { - convert(new ProcessBuffer(32000, 32000, 2, 1)); - } - - @Test - void upMix() { - convert(new ProcessBuffer(32000, 32000, 1, 2)); - } - - @Test - void downSampleDownMix() { - convert(new ProcessBuffer(48000, 44100, 2, 1)); - } - - @Test - void downSampleUpMix() { - convert(new ProcessBuffer(48000, 44100, 1, 2)); - } - - @Test - void upSampleDownMix() { - convert(new ProcessBuffer(44100, 48000, 2, 1)); - } - - @Test - void upSampleUpMix() { - convert(new ProcessBuffer(44100, 48000, 1, 2)); - } - - @Test - void targetBufferUnderflow() { - ProcessBuffer buffer = new ProcessBuffer(48000, 24000, 2, 2); - buffer.setTargetBufferSize(buffer.frameSizeOut / 2); - - assertThrows(IllegalArgumentException.class, () -> { - convert(buffer); - }); - } - - private static void convert(ProcessBuffer buffer) { - AudioConverter converter = new AudioConverter(buffer.sampleRateIn, - buffer.channelsIn, buffer.sampleRateOut, buffer.channelsOut); - converter.convert(buffer.src, buffer.dst); - converter.dispose(); - } - - - - private static class ProcessBuffer { - - final int bytesPerFrame = 2; - - final int channelsIn; - final int channelsOut; - - final int sampleRateIn; - final int sampleRateOut; - - final int nSamplesIn; - final int nSamplesOut; - - final int frameSizeIn; - final int frameSizeOut; - - byte[] src; - byte[] dst; - - AudioProcessingStreamConfig streamConfigIn; - AudioProcessingStreamConfig streamConfigOut; - - - ProcessBuffer(int sampleRateIn, int sampleRateOut, int channelsIn, int channelsOut) { - this.sampleRateIn = sampleRateIn; - this.sampleRateOut = sampleRateOut; - this.channelsIn = channelsIn; - this.channelsOut = channelsOut; - - nSamplesIn = sampleRateIn / 100; // 10 ms frame - nSamplesOut = sampleRateOut / 100; - frameSizeIn = nSamplesIn * channelsIn; - frameSizeOut = Math.max(nSamplesIn, nSamplesOut) * channelsOut; - - src = new byte[frameSizeIn * bytesPerFrame]; - dst = new byte[frameSizeOut * bytesPerFrame]; - - streamConfigIn = new AudioProcessingStreamConfig(sampleRateIn, channelsIn); - streamConfigOut = new AudioProcessingStreamConfig(sampleRateOut, channelsOut); - } - - void setTargetBufferSize(int size) { - dst = new byte[size]; - } - } -} diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/AudioDeviceModuleTest.java b/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/AudioDeviceModuleTest.java deleted file mode 100644 index 4f72959..0000000 --- a/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/AudioDeviceModuleTest.java +++ /dev/null @@ -1,48 +0,0 @@ -package dev.onvoid.webrtc.media.audio; - -import org.junit.jupiter.api.*; - -class AudioDeviceModuleTest { - - private AudioDeviceModule module; - - - @BeforeEach - void initModule() { - module = new AudioDeviceModule(AudioLayer.kDummyAudio); - } - - @AfterEach - void disposeModule() { - module.dispose(); - } - - @Test - void setAudioSink() { - AudioSink sink = new AudioSink() { - - @Override - public void onRecordedData(byte[] audioSamples, int nSamples, - int nBytesPerSample, int nChannels, int samplesPerSec, - int totalDelayMS, int clockDrift) { - - } - }; - - module.setAudioSink(sink); - } - - @Test - void setAudioSource() { - AudioSource source = new AudioSource() { - - @Override - public int onPlaybackData(byte[] audioSamples, int nSamples, - int nBytesPerSample, int nChannels, int samplesPerSec) { - return 0; - } - }; - - module.setAudioSource(source); - } -} diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/AudioProcessingTest.java b/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/AudioProcessingTest.java deleted file mode 100644 index b5b19f0..0000000 --- a/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/AudioProcessingTest.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.assertFalse; - -import dev.onvoid.webrtc.media.audio.AudioProcessingConfig.NoiseSuppression; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class AudioProcessingTest { - - private AudioProcessing audioProcessing; - - - @BeforeEach - void init() { - audioProcessing = new AudioProcessing(); - } - - @AfterEach - void dispose() { - audioProcessing.dispose(); - } - - @Test - void applyConfig() { - AudioProcessingConfig config = new AudioProcessingConfig(); - config.pipeline.maximumInternalProcessingRate = 48000; - config.pipeline.multiChannelRender = false; - config.pipeline.multiChannelCapture = false; - config.pipeline.captureDownmixMethod = AudioProcessingConfig.Pipeline.DownmixMethod.AverageChannels; - - config.echoCanceller.enabled = true; - config.echoCanceller.enforceHighPassFiltering = true; - - config.gainControllerDigital.enabled = true; - config.gainControllerDigital.inputVolumeController.enabled = true; - - config.highPassFilter.enabled = true; - - config.noiseSuppression.enabled = true; - config.noiseSuppression.level = NoiseSuppression.Level.HIGH; - - audioProcessing.applyConfig(config); - } - - @Test - void applyConfig_withGainController() { - AudioProcessingConfig config = new AudioProcessingConfig(); - config.gainController.enabled = true; - config.gainController.mode = AudioProcessingConfig.GainController.Mode.AdaptiveDigital; - config.gainController.targetLevelDbfs = 6; - config.gainController.compressionGainDb = 10; - config.gainController.enableLimiter = true; - - // Analog sub-config - AudioProcessingConfig.GainController.AnalogGainController agc = config.gainController.analogGainController; - agc.enabled = true; - agc.enableDigitalAdaptive = true; - agc.clippedLevelMin = 60; - agc.clippedLevelStep = 10; - agc.clippedRatioThreshold = 0.2f; - agc.clippedWaitFrames = 200; - - // Clipping predictor sub-config - AudioProcessingConfig.GainController.AnalogGainController.ClippingPredictor cp = agc.clippingPredictor; - cp.enabled = true; - cp.mode = AudioProcessingConfig.GainController.AnalogGainController.ClippingPredictor.Mode.AdaptiveStepClippingPeakPrediction; - cp.windowLength = 6; - cp.referenceWindowLength = 6; - cp.referenceWindowDelay = 4; - cp.clippingThreshold = -2.0f; - cp.crestFactorMargin = 2.5f; - cp.usePredictedStep = true; - - audioProcessing.applyConfig(config); - } - - @Test - void gainController_defaults() { - AudioProcessingConfig cfg = new AudioProcessingConfig(); - AudioProcessingConfig.GainController gc = cfg.gainController; - - assertFalse(gc.enabled, "AGC1 should be disabled by default"); - assertEquals(3, gc.targetLevelDbfs, "Default targetLevelDbfs"); - assertEquals(9, gc.compressionGainDb, "Default compressionGainDb"); - assertTrue(gc.enableLimiter, "Limiter enabled by default"); - assertEquals(AudioProcessingConfig.GainController.Mode.AdaptiveAnalog, gc.mode, - "Default mode is AdaptiveAnalog"); - - AudioProcessingConfig.GainController.AnalogGainController agc = gc.analogGainController; - assertTrue(agc.enabled, "AnalogGainController enabled by default"); - assertEquals(0, agc.startupMinVolume, "startupMinVolume default"); - assertEquals(70, agc.clippedLevelMin, "clippedLevelMin default"); - assertTrue(agc.enableDigitalAdaptive, "enableDigitalAdaptive default"); - assertEquals(15, agc.clippedLevelStep, "clippedLevelStep default"); - assertEquals(0.1f, agc.clippedRatioThreshold, 0.0001f, - "clippedRatioThreshold default"); - assertEquals(300, agc.clippedWaitFrames, "clippedWaitFrames default"); - - AudioProcessingConfig.GainController.AnalogGainController.ClippingPredictor cp = agc.clippingPredictor; - assertFalse(cp.enabled, "ClippingPredictor disabled by default"); - assertEquals(AudioProcessingConfig.GainController.AnalogGainController.ClippingPredictor.Mode.ClippingEventPrediction, cp.mode); - assertEquals(5, cp.windowLength); - assertEquals(5, cp.referenceWindowLength); - assertEquals(5, cp.referenceWindowDelay); - assertEquals(-1.0f, cp.clippingThreshold, 0.0001f); - assertEquals(3.0f, cp.crestFactorMargin, 0.0001f); - assertTrue(cp.usePredictedStep); - } - - @Test - void gainController_mutate_all_fields() { - AudioProcessingConfig cfg = new AudioProcessingConfig(); - AudioProcessingConfig.GainController gc = cfg.gainController; - - gc.enabled = true; - gc.targetLevelDbfs = 6; - gc.compressionGainDb = 12; - gc.enableLimiter = false; - gc.mode = AudioProcessingConfig.GainController.Mode.AdaptiveDigital; - - AudioProcessingConfig.GainController.AnalogGainController agc = gc.analogGainController; - agc.enabled = false; - agc.startupMinVolume = 7; - agc.clippedLevelMin = 50; - agc.enableDigitalAdaptive = false; - agc.clippedLevelStep = 10; - agc.clippedRatioThreshold = 0.25f; - agc.clippedWaitFrames = 123; - - AudioProcessingConfig.GainController.AnalogGainController.ClippingPredictor cp = agc.clippingPredictor; - cp.enabled = true; - cp.mode = AudioProcessingConfig.GainController.AnalogGainController.ClippingPredictor.Mode.AdaptiveStepClippingPeakPrediction; - cp.windowLength = 9; - cp.referenceWindowLength = 8; - cp.referenceWindowDelay = 2; - cp.clippingThreshold = -3.5f; - cp.crestFactorMargin = 1.25f; - cp.usePredictedStep = false; - - // Assertions reflect mutations - assertTrue(gc.enabled); - assertEquals(6, gc.targetLevelDbfs); - assertEquals(12, gc.compressionGainDb); - assertFalse(gc.enableLimiter); - assertEquals(AudioProcessingConfig.GainController.Mode.AdaptiveDigital, gc.mode); - - assertFalse(agc.enabled); - assertEquals(7, agc.startupMinVolume); - assertEquals(50, agc.clippedLevelMin); - assertFalse(agc.enableDigitalAdaptive); - assertEquals(10, agc.clippedLevelStep); - assertEquals(0.25f, agc.clippedRatioThreshold, 0.0001f); - assertEquals(123, agc.clippedWaitFrames); - - assertTrue(cp.enabled); - assertEquals(AudioProcessingConfig.GainController.AnalogGainController.ClippingPredictor.Mode.AdaptiveStepClippingPeakPrediction, cp.mode); - assertEquals(9, cp.windowLength); - assertEquals(8, cp.referenceWindowLength); - assertEquals(2, cp.referenceWindowDelay); - assertEquals(-3.5f, cp.clippingThreshold, 0.0001f); - assertEquals(1.25f, cp.crestFactorMargin, 0.0001f); - assertFalse(cp.usePredictedStep); - } - - @Test - void captureLevelAdjustment_defaults() { - AudioProcessingConfig cfg = new AudioProcessingConfig(); - AudioProcessingConfig.CaptureLevelAdjustment cla = cfg.captureLevelAdjustment; - - assertFalse(cla.enabled, "CLA disabled by default"); - assertEquals(1.0f, cla.preGainFactor, 0.0001f); - assertEquals(1.0f, cla.postGainFactor, 0.0001f); - AudioProcessingConfig.CaptureLevelAdjustment.AnalogMicGainEmulation ame = cla.analogMicGainEmulation; - assertFalse(ame.enabled, "AnalogMicGainEmulation disabled by default"); - assertEquals(255, ame.initialLevel, "AnalogMicGainEmulation initialLevel default"); - } - - @Test - void captureLevelAdjustment_mutate_all_fields() { - AudioProcessingConfig cfg = new AudioProcessingConfig(); - AudioProcessingConfig.CaptureLevelAdjustment cla = cfg.captureLevelAdjustment; - - cla.enabled = true; - cla.preGainFactor = 0.75f; - cla.postGainFactor = 1.25f; - cla.analogMicGainEmulation.enabled = true; - cla.analogMicGainEmulation.initialLevel = 200; - - // Should not throw and should be accepted by native ApplyConfig - audioProcessing.applyConfig(cfg); - - // Validate mutations remain in Java object - assertTrue(cla.enabled); - assertEquals(0.75f, cla.preGainFactor, 0.0001f); - assertEquals(1.25f, cla.postGainFactor, 0.0001f); - assertTrue(cla.analogMicGainEmulation.enabled); - assertEquals(200, cla.analogMicGainEmulation.initialLevel); - } - - @Test - void getStats() { - assertNotNull(audioProcessing.getStatistics()); - } - - @Test - void processByteStream() { - ProcessBuffer buffer = new ProcessBuffer(48000, 48000, 1, 1); - - assertEquals(0, process(audioProcessing, buffer)); - } - - @Test - void processByteStreamDownMix() { - ProcessBuffer buffer = new ProcessBuffer(48000, 44100, 2, 1); - - assertEquals(0, process(audioProcessing, buffer)); - } - - @Test - void processByteStreamUpMix() { - ProcessBuffer buffer = new ProcessBuffer(48000, 44100, 1, 2); - - assertEquals(0, process(audioProcessing, buffer)); - } - - @Test - void processReverseStream() { - ProcessBuffer buffer = new ProcessBuffer(48000, 48000, 1, 1); - - assertEquals(0, processReverse(audioProcessing, buffer)); - } - - @Test - void streamDelay() { - int delay = 70; - - audioProcessing.setStreamDelayMs(delay); - - assertEquals(delay, audioProcessing.getStreamDelayMs()); - } - - private static int process(AudioProcessing audioProcessing, ProcessBuffer buffer) { - return audioProcessing.processStream(buffer.src, buffer.streamConfigIn, - buffer.streamConfigOut, buffer.dst); - } - - private static int processReverse(AudioProcessing audioProcessing, ProcessBuffer buffer) { - return audioProcessing.processReverseStream(buffer.src, buffer.streamConfigIn, - buffer.streamConfigOut, buffer.dst); - } - - - - private static class ProcessBuffer { - - final int bytesPerFrame = 2; - - final int channelsIn; - final int channelsOut; - - final int sampleRateIn; - final int sampleRateOut; - - final int nSamplesIn; - final int nSamplesOut; - - final int frameSizeIn; - final int frameSizeOut; - - byte[] src; - byte[] dst; - - AudioProcessingStreamConfig streamConfigIn; - AudioProcessingStreamConfig streamConfigOut; - - - ProcessBuffer(int sampleRateIn, int sampleRateOut, int channelsIn, int channelsOut) { - this.sampleRateIn = sampleRateIn; - this.sampleRateOut = sampleRateOut; - this.channelsIn = channelsIn; - this.channelsOut = channelsOut; - - nSamplesIn = sampleRateIn / 100; // 10 ms frame - nSamplesOut = sampleRateOut / 100; - frameSizeIn = nSamplesIn * bytesPerFrame * channelsIn; - frameSizeOut = Math.max(nSamplesIn, nSamplesOut) * bytesPerFrame * channelsOut; - - src = new byte[frameSizeIn]; - dst = new byte[frameSizeOut]; - - streamConfigIn = new AudioProcessingStreamConfig(sampleRateIn, channelsIn); - streamConfigOut = new AudioProcessingStreamConfig(sampleRateOut, channelsOut); - } - } -} diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/AudioResamplerTest.java b/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/AudioResamplerTest.java deleted file mode 100644 index 29e1131..0000000 --- a/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/AudioResamplerTest.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class AudioResamplerTest { - - private AudioResampler resampler; - - - @BeforeEach - void init() { - resampler = new AudioResampler(); - } - - @AfterEach - void dispose() { - resampler.dispose(); - } - - @Test - void targetBufferUnderflow() { - SampleBuffer buffer = new SampleBuffer(48000, 24000, 1); - buffer.setTargetBufferSize(buffer.frameSizeOut / 2); - - assertThrows(IllegalArgumentException.class, () -> resample(resampler, buffer)); - } - - @Test - void constructorParameters() { - SampleBuffer buffer = new SampleBuffer(48000, 44100, 2); - AudioResampler resampler = new AudioResampler(48000, 44100, 2); - - int result = resample(resampler, buffer); - - resampler.dispose(); - - assertEquals(buffer.nSamplesOut, result); - } - - @Test - void downSample() { - SampleBuffer buffer = new SampleBuffer(48000, 44100, 1); - - int result = resample(resampler, buffer); - - assertEquals(buffer.nSamplesOut, result); - } - - @Test - void upSample() { - SampleBuffer buffer = new SampleBuffer(32000, 48000, 1); - - int result = resample(resampler, buffer); - - assertEquals(buffer.nSamplesOut, result); - } - - private static int resample(AudioResampler resampler, SampleBuffer buffer) { - return resampler.resample(buffer.src, buffer.nSamplesIn, buffer.dst, buffer.nSamplesOut, 1); - } - - - - private static class SampleBuffer { - - final int bytesPerFrame = 2; - - final int channels; - - final int sampleRateIn; - final int sampleRateOut; - - final int nSamplesIn; - final int nSamplesOut; - - final int frameSizeIn; - final int frameSizeOut; - - byte[] src; - byte[] dst; - - - SampleBuffer(int sampleRateIn, int sampleRateOut, int channels) { - this.channels = channels; - this.sampleRateIn = sampleRateIn; - this.sampleRateOut = sampleRateOut; - - nSamplesIn = AudioResampler.getSamplesPerChannel(sampleRateIn); // 10 ms frame - nSamplesOut = AudioResampler.getSamplesPerChannel(sampleRateOut); - frameSizeIn = nSamplesIn * bytesPerFrame; - frameSizeOut = nSamplesOut * bytesPerFrame; - - src = new byte[frameSizeIn]; - dst = new byte[frameSizeOut]; - } - - void setTargetBufferSize(int size) { - dst = new byte[size]; - } - } -} diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/AudioTrackTests.java b/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/AudioTrackTests.java deleted file mode 100644 index 961b537..0000000 --- a/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/AudioTrackTests.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -import static org.junit.jupiter.api.Assertions.*; - -import dev.onvoid.webrtc.TestBase; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class AudioTrackTests extends TestBase { - - private AudioTrack audioTrack; - - - @BeforeEach - void init() { - AudioOptions audioOptions = new AudioOptions(); - AudioTrackSource audioSource = factory.createAudioSource(audioOptions); - - audioTrack = factory.createAudioTrack("audioTrack", audioSource); - } - - @AfterEach - void dispose() { - audioTrack.dispose(); - } - - @Test - void disableEnableTrack() { - audioTrack.setEnabled(false); - - assertFalse(audioTrack.isEnabled()); - - audioTrack.setEnabled(true); - - assertTrue(audioTrack.isEnabled()); - } - - @Test - void addNullSink() { - assertThrows(NullPointerException.class, () -> audioTrack.addSink(null)); - } - - @Test - void removeNullSink() { - assertThrows(NullPointerException.class, () -> audioTrack.removeSink(null)); - } - - @Test - void addRemoveSink() { - AudioTrackSink sink = (data, bitsPerSample, sampleRate, channels, frames) -> { }; - - audioTrack.addSink(sink); - audioTrack.removeSink(sink); - } - -} diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/CustomAudioSourceTest.java b/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/CustomAudioSourceTest.java deleted file mode 100644 index 26a96ab..0000000 --- a/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/CustomAudioSourceTest.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2025 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -import static org.junit.jupiter.api.Assertions.*; - -import dev.onvoid.webrtc.TestBase; -import dev.onvoid.webrtc.media.MediaSource; -import dev.onvoid.webrtc.media.SyncClock; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -class CustomAudioSourceTest extends TestBase { - - private CustomAudioSource customAudioSource; - - - @BeforeEach - void init() { - customAudioSource = new CustomAudioSource(); - } - - @AfterEach - void dispose() { - - } - - @Test - void stateAfterCreation() { - assertEquals(MediaSource.State.LIVE, customAudioSource.getState()); - } - - @Test - void addNullSink() { - assertThrows(NullPointerException.class, () -> { - AudioTrack audioTrack = factory.createAudioTrack("audioTrack", customAudioSource); - audioTrack.addSink(null); - audioTrack.dispose(); - }); - } - - @Test - void removeNullSink() { - assertThrows(NullPointerException.class, () -> { - AudioTrack audioTrack = factory.createAudioTrack("audioTrack", customAudioSource); - audioTrack.removeSink(null); - audioTrack.dispose(); - }); - } - - @Test - void addRemoveSink() { - AudioTrack audioTrack = factory.createAudioTrack("audioTrack", customAudioSource); - AudioTrackSink sink = (data, bitsPerSample, sampleRate, channels, frames) -> { }; - - audioTrack.addSink(sink); - audioTrack.removeSink(sink); - audioTrack.dispose(); - } - - @Test - void pushAudioData() { - // 16-bit, 48kHz, stereo, 10ms - testAudioFormat(16, 48000, 2, 480); - } - - @Test - void pushAudioWithDifferentFormats() { - testAudioFormat(8, 8000, 1, 80); // 8-bit, 8kHz, mono, 10ms - testAudioFormat(16, 16000, 1, 160); // 16-bit, 16kHz, mono, 10ms - testAudioFormat(16, 44100, 2, 441); // 16-bit, 44.1kHz, stereo, 10ms - testAudioFormat(16, 48000, 2, 480); // 16-bit, 48kHz, stereo, 10ms - } - - @Test - void constructWithSyncClock() { - // Create a SyncClock. - SyncClock clock = new SyncClock(); - - // Create a CustomAudioSource with the clock. - CustomAudioSource sourceWithClock = new CustomAudioSource(clock); - - // Verify the source is created correctly. - assertEquals(MediaSource.State.LIVE, sourceWithClock.getState()); - - // Test basic functionality. - AudioTrack audioTrack = factory.createAudioTrack("audioTrack", sourceWithClock); - - final AtomicBoolean dataReceived = new AtomicBoolean(false); - AudioTrackSink testSink = (data, bits, rate, chans, frames) -> { - dataReceived.set(true); - }; - - audioTrack.addSink(testSink); - - // Create a buffer with test audio data. - byte[] audioData = new byte[480 * 2 * 2]; // 10ms of 48kHz stereo 16-bit audio - - // Push audio data. - sourceWithClock.pushAudio(audioData, 16, 48000, 2, 480); - - // Verify that our sink received the data. - assertTrue(dataReceived.get(), "Audio data was not received by the sink"); - - // Clean up - audioTrack.removeSink(testSink); - audioTrack.dispose(); - sourceWithClock.dispose(); - clock.dispose(); - } - - private void testAudioFormat(int bitsPerSample, int sampleRate, int channels, int frameCount) { - AudioTrack audioTrack = factory.createAudioTrack("audioTrack", customAudioSource); - - final AtomicBoolean dataReceived = new AtomicBoolean(false); - final AtomicInteger receivedBitsPerSample = new AtomicInteger(0); - final AtomicInteger receivedSampleRate = new AtomicInteger(0); - final AtomicInteger receivedChannels = new AtomicInteger(0); - final AtomicInteger receivedFrames = new AtomicInteger(0); - - AudioTrackSink testSink = (data, bits, rate, chans, frames) -> { - dataReceived.set(true); - receivedBitsPerSample.set(bits); - receivedSampleRate.set(rate); - receivedChannels.set(chans); - receivedFrames.set(frames); - }; - - audioTrack.addSink(testSink); - - // Create a buffer with test audio data (silence in this case). - int bytesPerSample = bitsPerSample / 8; - byte[] audioData = new byte[frameCount * channels * bytesPerSample]; - - customAudioSource.pushAudio(audioData, bitsPerSample, sampleRate, channels, frameCount); - - // Verify that our sink received the data with correct parameters. - assertTrue(dataReceived.get(), "Audio data was not received by the sink"); - assertEquals(bitsPerSample, receivedBitsPerSample.get(), "Bits per sample doesn't match"); - assertEquals(sampleRate, receivedSampleRate.get(), "Sample rate doesn't match"); - assertEquals(channels, receivedChannels.get(), "Channel count doesn't match"); - assertEquals(frameCount, receivedFrames.get(), "Frame count doesn't match"); - - // Clean up. - audioTrack.removeSink(testSink); - audioTrack.dispose(); - } -} \ No newline at end of file diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/DummyAudioDeviceModuleTest.java b/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/DummyAudioDeviceModuleTest.java deleted file mode 100644 index 42f2345..0000000 --- a/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/DummyAudioDeviceModuleTest.java +++ /dev/null @@ -1,44 +0,0 @@ -package dev.onvoid.webrtc.media.audio; - -import dev.onvoid.webrtc.PeerConnectionFactory; -import dev.onvoid.webrtc.RTCConfiguration; -import dev.onvoid.webrtc.RTCPeerConnection; - -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInstance; -import org.junit.jupiter.api.parallel.Execution; -import org.junit.jupiter.api.parallel.ExecutionMode; - -import static org.junit.jupiter.api.Assertions.assertNotNull; - -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -@Execution(ExecutionMode.SAME_THREAD) -public class DummyAudioDeviceModuleTest { - - private PeerConnectionFactory factory; - - - @BeforeAll - void initFactory() { - factory = new PeerConnectionFactory(new AudioDeviceModule( - AudioLayer.kDummyAudio)); - } - - @AfterAll - void disposeFactory() { - factory.dispose(); - } - - @Test - void createPeerConnectionWithDummyAudio() { - RTCConfiguration config = new RTCConfiguration(); - RTCPeerConnection peerConnection = factory.createPeerConnection(config, - candidate -> { }); - - assertNotNull(peerConnection); - - peerConnection.close(); - } -} diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/HeadlessADMIntegrationTest.java b/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/HeadlessADMIntegrationTest.java deleted file mode 100644 index eb3b1a1..0000000 --- a/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/HeadlessADMIntegrationTest.java +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright 2025 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -import static org.junit.jupiter.api.Assertions.*; - -import java.util.Collections; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicReference; - -import dev.onvoid.webrtc.*; -import dev.onvoid.webrtc.media.MediaStreamTrack; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInstance; -import org.junit.jupiter.api.parallel.Execution; -import org.junit.jupiter.api.parallel.ExecutionMode; - -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -@Execution(ExecutionMode.SAME_THREAD) -public class HeadlessADMIntegrationTest { - - @Test - void audioReceivedOnSink() throws Exception { - HeadlessAudioDeviceModule adm = new HeadlessAudioDeviceModule(); - PeerConnectionFactory factory = new PeerConnectionFactory(adm); - - // Ensure the playout pipeline is started (headless output). - adm.initPlayout(); - adm.startPlayout(); - - adm.initRecording(); - adm.startRecording(); - - RTCConfiguration cfg = new RTCConfiguration(); - - // Latches and flags for coordination. - CountDownLatch connectedLatch = new CountDownLatch(1); - CountDownLatch sinkAddedLatch = new CountDownLatch(1); - CountDownLatch sinkFramesLatch = new CountDownLatch(10); - CountDownLatch senderClosedLatch = new CountDownLatch(1); - CountDownLatch receiverClosedLatch = new CountDownLatch(1); - - final AtomicReference senderPcRef = new AtomicReference<>(); - final AtomicReference receiverPcRef = new AtomicReference<>(); - - // Receiver observer: handle ICE and attach AudioTrack sink on onTrack. - PeerConnectionObserver receiverObserver = new PeerConnectionObserver() { - @Override - public void onIceCandidate(RTCIceCandidate candidate) { - // Forward to sender. - RTCPeerConnection spc = senderPcRef.get(); - if (spc != null) { - spc.addIceCandidate(candidate); - } - } - - @Override - public void onConnectionChange(RTCPeerConnectionState state) { - if (state == RTCPeerConnectionState.CONNECTED) { - connectedLatch.countDown(); - } - else if (state == RTCPeerConnectionState.CLOSED) { - receiverClosedLatch.countDown(); - } - } - - @Override - public void onTrack(RTCRtpTransceiver transceiver) { - MediaStreamTrack track = transceiver.getReceiver().getTrack(); - if (MediaStreamTrack.AUDIO_TRACK_KIND.equals(track.getKind())) { - AudioTrack audioTrack = (AudioTrack) track; - AudioTrackSink sink = (data, bitsPerSample, sampleRate, channels, frames) -> { - if (frames > 0) { - sinkFramesLatch.countDown(); - } - }; - audioTrack.addSink(sink); - - sinkAddedLatch.countDown(); - } - } - }; - - // Sender observer: forward ICE to receiver, and listen for CLOSED. - PeerConnectionObserver senderObserver = new PeerConnectionObserver() { - @Override - public void onIceCandidate(RTCIceCandidate candidate) { - RTCPeerConnection rpc = receiverPcRef.get(); - if (rpc != null) { - rpc.addIceCandidate(candidate); - } - } - - @Override - public void onConnectionChange(RTCPeerConnectionState state) { - if (state == RTCPeerConnectionState.CLOSED) { - senderClosedLatch.countDown(); - } - } - }; - - RTCPeerConnection senderPc = factory.createPeerConnection(cfg, senderObserver); - RTCPeerConnection receiverPc = factory.createPeerConnection(cfg, receiverObserver); - senderPcRef.set(senderPc); - receiverPcRef.set(receiverPc); - - // Add an explicit receive-only audio transceiver on the receiver side. - AudioTrackSource rxSource = factory.createAudioSource(new AudioOptions()); - AudioTrack receiverTrack = factory.createAudioTrack("rx-audio", rxSource); - RTCRtpTransceiverInit recvOnlyInit = new RTCRtpTransceiverInit(); - recvOnlyInit.direction = RTCRtpTransceiverDirection.RECV_ONLY; - receiverPc.addTransceiver(receiverTrack, recvOnlyInit); - - // Create sender audio from CustomAudioSource and add to PC. - CustomAudioSource customSource = new CustomAudioSource(); - AudioTrack senderTrack = factory.createAudioTrack("audio0", customSource); - senderPc.addTrack(senderTrack, Collections.singletonList("stream0")); - - // SDP offer/answer exchange. - LocalCreateDescObserver createOfferObs = new LocalCreateDescObserver(); - senderPc.createOffer(new RTCOfferOptions(), createOfferObs); - RTCSessionDescription offer = createOfferObs.get(); - - LocalSetDescObserver setLocalOfferObs = new LocalSetDescObserver(); - senderPc.setLocalDescription(offer, setLocalOfferObs); - setLocalOfferObs.get(); - - LocalSetDescObserver setRemoteOfferObs = new LocalSetDescObserver(); - receiverPc.setRemoteDescription(offer, setRemoteOfferObs); - setRemoteOfferObs.get(); - - LocalCreateDescObserver createAnswerObs = new LocalCreateDescObserver(); - receiverPc.createAnswer(new RTCAnswerOptions(), createAnswerObs); - RTCSessionDescription answer = createAnswerObs.get(); - - LocalSetDescObserver setLocalAnswerObs = new LocalSetDescObserver(); - receiverPc.setLocalDescription(answer, setLocalAnswerObs); - setLocalAnswerObs.get(); - - LocalSetDescObserver setRemoteAnswerObs = new LocalSetDescObserver(); - senderPc.setRemoteDescription(answer, setRemoteAnswerObs); - setRemoteAnswerObs.get(); - - // Wait for connection established, but also ensure sink was installed. - assertTrue(connectedLatch.await(10, TimeUnit.SECONDS), - "Peer connection did not reach CONNECTED state in time"); - - // Push a few frames of audio data via CustomAudioSource. - final int bitsPerSample = 16; - final int sampleRate = 48000; - final int channels = 2; - final int frameCount = 480; // 10ms @ 48kHz - byte[] silence = new byte[frameCount * channels * (bitsPerSample / 8)]; - - // Wait for onTrack to fire and sink to be added before sending. - assertTrue(sinkAddedLatch.await(5, TimeUnit.SECONDS), - "Audio sink was not added in time"); - - for (int i = 0; i < 10; i++) { // ~100ms of audio - customSource.pushAudio(silence, bitsPerSample, sampleRate, channels, frameCount); - Thread.sleep(10); - } - - // Validate that we received audio frames on the remote track sink. - assertTrue(sinkFramesLatch.await(3, TimeUnit.SECONDS), - "No audio frames received on remote AudioTrack sink"); - - adm.stopPlayout(); - adm.stopRecording(); - - // Cleanup. - senderPc.close(); - receiverPc.close(); - - // Wait for CLOSED state notifications to avoid races in native teardown. - assertTrue(senderClosedLatch.await(5, TimeUnit.SECONDS), - "Sender PC did not reach CLOSED state in time"); - assertTrue(receiverClosedLatch.await(5, TimeUnit.SECONDS), - "Receiver PC did not reach CLOSED state in time"); - -// senderTrack.dispose(); -// receiverTrack.dispose(); - customSource.dispose(); - - factory.dispose(); - - adm.dispose(); - } - - - - private static class LocalCreateDescObserver implements CreateSessionDescriptionObserver { - - private final CountDownLatch latch = new CountDownLatch(1); - private RTCSessionDescription description; - private String error; - - - @Override - public void onSuccess(RTCSessionDescription description) { - this.description = description; - latch.countDown(); - } - - @Override - public void onFailure(String error) { - this.error = error; - latch.countDown(); - } - - RTCSessionDescription get() throws Exception { - boolean completed = latch.await(10, TimeUnit.SECONDS); - if (!completed) { - throw new TimeoutException("CreateSessionDescription timed out"); - } - if (error != null) { - throw new IllegalStateException("CreateSessionDescription failed: " + error); - } - return description; - } - } - - - - private static class LocalSetDescObserver implements SetSessionDescriptionObserver { - - private final CountDownLatch latch = new CountDownLatch(1); - private String error; - - - @Override - public void onSuccess() { - latch.countDown(); - } - - @Override - public void onFailure(String error) { - this.error = error; - latch.countDown(); - } - - void get() throws Exception { - boolean completed = latch.await(10, TimeUnit.SECONDS); - if (!completed) { - throw new TimeoutException("SetSessionDescription timed out"); - } - if (error != null) { - throw new IllegalStateException("SetSessionDescription failed: " + error); - } - } - } -} diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/HeadlessADMTest.java b/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/HeadlessADMTest.java deleted file mode 100644 index a2a9e1f..0000000 --- a/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/HeadlessADMTest.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2025 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -import static org.junit.jupiter.api.Assertions.*; - -import java.util.List; - -import dev.onvoid.webrtc.PeerConnectionFactory; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInstance; -import org.junit.jupiter.api.parallel.Execution; -import org.junit.jupiter.api.parallel.ExecutionMode; - -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -@Execution(ExecutionMode.SAME_THREAD) -public class HeadlessADMTest { - - private HeadlessAudioDeviceModule adm; - - - @BeforeEach - void setUp() { - adm = new HeadlessAudioDeviceModule(); - } - - @AfterEach - void tearDown() { - if (adm != null) { - try { - adm.stopPlayout(); - } - catch (Throwable ignored) { - // Ignore any exceptions during stopPlayout, as it may not be initialized. - } - try { - adm.stopRecording(); - } - catch (Throwable ignored) { - // Ignore any exceptions during stopRecording, as it may not be initialized. - } - adm.dispose(); - adm = null; - } - } - - @Test - void getPlayoutDevices_returnsAtLeastOneDevice() { - List devices = adm.getPlayoutDevices(); - assertNotNull(devices, "Playout devices list should not be null"); - assertFalse(devices.isEmpty(), "Headless module should expose at least one dummy playout device"); - } - - @Test - void getRecordingDevices_returnsAtLeastOneDevice() { - List devices = adm.getRecordingDevices(); - assertNotNull(devices, "Recording devices list should not be null"); - assertFalse(devices.isEmpty(), "Headless module should expose at least one dummy recording device"); - } - - @Test - void startStopPlayout_afterInit_doesNotThrow() { - assertDoesNotThrow(() -> { - adm.initPlayout(); - adm.startPlayout(); - adm.stopPlayout(); - }); - } - - @Test - void startStopRecording_afterInit_doesNotThrow() { - assertDoesNotThrow(() -> { - adm.initRecording(); - adm.startRecording(); - adm.stopRecording(); - }); - } - - @Test - void startPlayout_withoutInit_throwsException() { - assertThrows(Error.class, () -> adm.startPlayout()); - } - - @Test - void startRecording_withoutInit_throwsException() { - assertThrows(Error.class, () -> adm.startRecording()); - } - - @Test - void initPeerConnectionFactory() { - PeerConnectionFactory factory = new PeerConnectionFactory(adm); - factory.dispose(); - } -} diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/VoiceActivityDetectorTest.java b/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/VoiceActivityDetectorTest.java deleted file mode 100644 index 3a869ba..0000000 --- a/webrtc/src/test/java/dev/onvoid/webrtc/media/audio/VoiceActivityDetectorTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2021 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.audio; - -import static org.junit.jupiter.api.Assertions.*; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -public class VoiceActivityDetectorTest { - - private VoiceActivityDetector detector; - - - @BeforeEach - void setUp() { - detector = new VoiceActivityDetector(); - } - - @AfterEach - void tearDown() { - if (detector != null) { - detector.dispose(); - } - } - - @Test - void testInitialization() { - assertNotNull(detector, "Detector should be initialized"); - } - - @Test - void testProcessAndGetProbability() { - // Create sample audio data (silence - all zeros). - byte[] silenceData = new byte[320]; // 10ms at 16kHz mono with 16-bit samples - int samplesPerChannel = 160; - int sampleRate = 16000; - - // Process silent audio. - detector.process(silenceData, samplesPerChannel, sampleRate); - - float probability = detector.getLastVoiceProbability(); - - assertTrue(probability >= 0.0f && probability <= 1.0f, - "Probability should be between 0.0 and 1.0"); - } - - @Test - void testDispose() { - // The First operation should work. - detector.process(new byte[320], 160, 16000); - - // Dispose resources. - detector.dispose(); - - // After disposal, operations should either throw an exception or be safe to call. - assertThrows(Exception.class, () -> { - detector.process(new byte[320], 160, 16000); - }); - - detector = null; - } - -} diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/media/video/CustomVideoSourceTest.java b/webrtc/src/test/java/dev/onvoid/webrtc/media/video/CustomVideoSourceTest.java deleted file mode 100644 index 04e36cc..0000000 --- a/webrtc/src/test/java/dev/onvoid/webrtc/media/video/CustomVideoSourceTest.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright 2025 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.video; - -import static org.junit.jupiter.api.Assertions.*; - -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -import dev.onvoid.webrtc.TestBase; -import dev.onvoid.webrtc.media.MediaSource; -import dev.onvoid.webrtc.media.SyncClock; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class CustomVideoSourceTest extends TestBase { - - private CustomVideoSource customVideoSource; - - - @BeforeEach - void init() { - customVideoSource = new CustomVideoSource(); - } - - @AfterEach - void dispose() { - if (customVideoSource != null) { - customVideoSource.dispose(); - customVideoSource = null; - } - } - - @Test - void stateAfterCreation() { - assertEquals(MediaSource.State.LIVE, customVideoSource.getState()); - } - - @Test - void addNullSink() { - assertThrows(NullPointerException.class, () -> { - VideoTrack videoTrack = factory.createVideoTrack("videoTrack", customVideoSource); - videoTrack.addSink(null); - videoTrack.dispose(); - }); - } - - @Test - void removeNullSink() { - assertThrows(NullPointerException.class, () -> { - VideoTrack videoTrack = factory.createVideoTrack("videoTrack", customVideoSource); - videoTrack.removeSink(null); - videoTrack.dispose(); - }); - } - - @Test - void addRemoveSink() { - VideoTrack videoTrack = factory.createVideoTrack("videoTrack", customVideoSource); - VideoTrackSink sink = new VideoTrackSink() { - @Override - public void onVideoFrame(VideoFrame frame) { - // Do nothing - } - }; - - videoTrack.addSink(sink); - videoTrack.removeSink(sink); - videoTrack.dispose(); - } - - @Test - void pushVideoFrame() { - // Test with 640x480 resolution - testVideoFrame(640, 480); - } - - @Test - void pushVideoFrameWithDifferentResolutions() { - testVideoFrame(320, 240); // QVGA - testVideoFrame(640, 480); // VGA - testVideoFrame(1280, 720); // HD - testVideoFrame(1920, 1080); // Full HD - } - - @Test - void constructWithSyncClock() { - // Create a SyncClock. - SyncClock clock = new SyncClock(); - - // Create a CustomVideoSource with the clock. - CustomVideoSource sourceWithClock = new CustomVideoSource(clock); - - // Verify the source is created correctly. - assertEquals(MediaSource.State.LIVE, sourceWithClock.getState()); - - // Test basic functionality. - VideoTrack videoTrack = factory.createVideoTrack("videoTrack", sourceWithClock); - - final AtomicBoolean frameReceived = new AtomicBoolean(false); - final AtomicInteger receivedWidth = new AtomicInteger(0); - final AtomicInteger receivedHeight = new AtomicInteger(0); - - VideoTrackSink testSink = new VideoTrackSink() { - @Override - public void onVideoFrame(VideoFrame frame) { - frameReceived.set(true); - receivedWidth.set(frame.buffer.getWidth()); - receivedHeight.set(frame.buffer.getHeight()); - } - }; - - videoTrack.addSink(testSink); - - // Create a test frame. - int width = 640; - int height = 480; - NativeI420Buffer buffer = NativeI420Buffer.allocate(width, height); - VideoFrame frame = new VideoFrame(buffer, System.nanoTime()); - - // Push the frame to the source. - sourceWithClock.pushFrame(frame); - - // Verify that our sink received the frame with correct parameters. - assertTrue(frameReceived.get(), "Video frame was not received by the sink"); - assertEquals(width, receivedWidth.get(), "Frame width doesn't match"); - assertEquals(height, receivedHeight.get(), "Frame height doesn't match"); - - // Clean up. - frame.release(); - videoTrack.removeSink(testSink); - videoTrack.dispose(); - sourceWithClock.dispose(); - clock.dispose(); - } - - private void testVideoFrame(int width, int height) { - VideoTrack videoTrack = factory.createVideoTrack("videoTrack", customVideoSource); - - final AtomicBoolean frameReceived = new AtomicBoolean(false); - final AtomicInteger receivedWidth = new AtomicInteger(0); - final AtomicInteger receivedHeight = new AtomicInteger(0); - - VideoTrackSink testSink = new VideoTrackSink() { - @Override - public void onVideoFrame(VideoFrame frame) { - frameReceived.set(true); - receivedWidth.set(frame.buffer.getWidth()); - receivedHeight.set(frame.buffer.getHeight()); - } - }; - - videoTrack.addSink(testSink); - - // Create a test frame with the specified resolution - NativeI420Buffer buffer = NativeI420Buffer.allocate(width, height); - VideoFrame frame = new VideoFrame(buffer, System.nanoTime()); - - // Push the frame to the source - customVideoSource.pushFrame(frame); - - // Verify that our sink received the frame with correct parameters - assertTrue(frameReceived.get(), "Video frame was not received by the sink"); - assertEquals(width, receivedWidth.get(), "Frame width doesn't match"); - assertEquals(height, receivedHeight.get(), "Frame height doesn't match"); - - // Clean up - frame.release(); - videoTrack.removeSink(testSink); - videoTrack.dispose(); - } -} \ No newline at end of file diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/media/video/VideoBufferConverterTest.java b/webrtc/src/test/java/dev/onvoid/webrtc/media/video/VideoBufferConverterTest.java deleted file mode 100644 index 943ff54..0000000 --- a/webrtc/src/test/java/dev/onvoid/webrtc/media/video/VideoBufferConverterTest.java +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Copyright 2025 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.video; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.nio.ByteBuffer; - -import dev.onvoid.webrtc.TestBase; -import dev.onvoid.webrtc.media.FourCC; - -import org.junit.jupiter.api.Test; - -class VideoBufferConverterTest extends TestBase { - - private static final int WIDTH = 32; - private static final int HEIGHT = 8; - - @Test - void convertFromI420ToByteArray() throws Exception { - NativeI420Buffer i420 = NativeI420Buffer.allocate(WIDTH, HEIGHT); - initializeI420Buffer(i420); - byte[] rgba = new byte[4 * WIDTH * HEIGHT]; - VideoBufferConverter.convertFromI420(i420, rgba, FourCC.RGBA); - verifyI420Buffer(i420, false); - verifyRGBAArray(rgba, true); - } - - @Test - void convertFromI420ToDirectBuffer() throws Exception { - NativeI420Buffer i420 = NativeI420Buffer.allocate(WIDTH, HEIGHT); - initializeI420Buffer(i420); - ByteBuffer rgba = ByteBuffer.allocateDirect(4 * WIDTH * HEIGHT); - VideoBufferConverter.convertFromI420(i420, rgba, FourCC.RGBA); - verifyI420Buffer(i420, false); - verifyRGBABuffer(rgba, true); - } - - @Test - void convertFromI420ToNonDirectBuffer() throws Exception { - NativeI420Buffer i420 = NativeI420Buffer.allocate(WIDTH, HEIGHT); - initializeI420Buffer(i420); - ByteBuffer rgba = ByteBuffer.allocate(4 * WIDTH * HEIGHT); - VideoBufferConverter.convertFromI420(i420, rgba, FourCC.RGBA); - verifyI420Buffer(i420, false); - verifyRGBABuffer(rgba, true); - } - - @Test - void convertFromI420ToReadOnlyDirectBuffer() throws Exception { - NativeI420Buffer i420 = NativeI420Buffer.allocate(WIDTH, HEIGHT); - initializeI420Buffer(i420); - ByteBuffer rgba = ByteBuffer.allocateDirect(4 * WIDTH * HEIGHT); - assertThrows(IllegalArgumentException.class, () -> { - VideoBufferConverter.convertFromI420(i420, rgba.asReadOnlyBuffer(), FourCC.RGBA); - }); - } - - @Test - void convertFromI420ToReadOnlyNonDirectBuffer() throws Exception { - NativeI420Buffer i420 = NativeI420Buffer.allocate(WIDTH, HEIGHT); - initializeI420Buffer(i420); - ByteBuffer rgba = ByteBuffer.allocate(4 * WIDTH * HEIGHT); - assertThrows(IllegalArgumentException.class, () -> { - VideoBufferConverter.convertFromI420(i420, rgba.asReadOnlyBuffer(), FourCC.RGBA); - }); - } - - @Test - void convertFromI420ToSmallByteArray() throws Exception { - NativeI420Buffer i420 = NativeI420Buffer.allocate(WIDTH, HEIGHT); - initializeI420Buffer(i420); - byte[] rgba = new byte[4 * WIDTH * HEIGHT - 1]; - assertThrows(RuntimeException.class, () -> { - VideoBufferConverter.convertFromI420(i420, rgba, FourCC.RGBA); - }); - } - - @Test - void convertFromI420ToSmallDirectBuffer() throws Exception { - NativeI420Buffer i420 = NativeI420Buffer.allocate(WIDTH, HEIGHT); - initializeI420Buffer(i420); - ByteBuffer rgba = ByteBuffer.allocateDirect(4 * WIDTH * HEIGHT - 1); - assertThrows(RuntimeException.class, () -> { - VideoBufferConverter.convertFromI420(i420, rgba, FourCC.RGBA); - }); - } - - @Test - void convertFromI420ToSmallNonDirectBuffer() throws Exception { - NativeI420Buffer i420 = NativeI420Buffer.allocate(WIDTH, HEIGHT); - initializeI420Buffer(i420); - ByteBuffer rgba = ByteBuffer.allocate(4 * WIDTH * HEIGHT - 1); - assertThrows(RuntimeException.class, () -> { - VideoBufferConverter.convertFromI420(i420, rgba, FourCC.RGBA); - }); - } - - @Test - void convertFromByteArrayToI420() throws Exception { - byte[] rgba = new byte[4 * WIDTH * HEIGHT]; - initializeRGBAArray(rgba); - NativeI420Buffer i420 = NativeI420Buffer.allocate(WIDTH, HEIGHT); - VideoBufferConverter.convertToI420(rgba, i420, FourCC.RGBA); - verifyRGBAArray(rgba, false); - verifyI420Buffer(i420, true); - } - - @Test - void convertFromDirectBufferToI420() throws Exception { - ByteBuffer rgba = ByteBuffer.allocateDirect(4 * WIDTH * HEIGHT); - initializeRGBABuffer(rgba); - rgba.rewind(); - NativeI420Buffer i420 = NativeI420Buffer.allocate(WIDTH, HEIGHT); - VideoBufferConverter.convertToI420(rgba, i420, FourCC.RGBA); - verifyRGBABuffer(rgba, false); - verifyI420Buffer(i420, true); - } - - @Test - void convertFromNonDirectBufferToI420() throws Exception { - ByteBuffer rgba = ByteBuffer.allocate(4 * WIDTH * HEIGHT); - initializeRGBABuffer(rgba); - rgba.rewind(); - NativeI420Buffer i420 = NativeI420Buffer.allocate(WIDTH, HEIGHT); - VideoBufferConverter.convertToI420(rgba, i420, FourCC.RGBA); - verifyRGBABuffer(rgba, false); - verifyI420Buffer(i420, true); - } - - @Test - void convertFromReadOnlyDirectBufferToI420() throws Exception { - ByteBuffer rgba = ByteBuffer.allocateDirect(4 * WIDTH * HEIGHT); - initializeRGBABuffer(rgba); - rgba.rewind(); - NativeI420Buffer i420 = NativeI420Buffer.allocate(WIDTH, HEIGHT); - VideoBufferConverter.convertToI420(rgba.asReadOnlyBuffer(), i420, FourCC.RGBA); - verifyRGBABuffer(rgba, false); - verifyI420Buffer(i420, true); - } - - @Test - void convertFromReadOnlyNonDirectBufferToI420() throws Exception { - ByteBuffer rgba = ByteBuffer.allocate(4 * WIDTH * HEIGHT); - initializeRGBABuffer(rgba); - rgba.rewind(); - NativeI420Buffer i420 = NativeI420Buffer.allocate(WIDTH, HEIGHT); - VideoBufferConverter.convertToI420(rgba.asReadOnlyBuffer(), i420, FourCC.RGBA); - verifyRGBABuffer(rgba, false); - verifyI420Buffer(i420, true); - } - - @Test - void convertFromSmallByteArrayToI420() throws Exception { - byte[] rgba = new byte[4 * WIDTH * HEIGHT - 1]; - initializeRGBAArray(rgba); - NativeI420Buffer i420 = NativeI420Buffer.allocate(WIDTH, HEIGHT); - assertThrows(RuntimeException.class, () -> { - VideoBufferConverter.convertToI420(rgba, i420, FourCC.RGBA); - }); - } - - @Test - void convertFromSmallDirectBufferToI420() throws Exception { - ByteBuffer rgba = ByteBuffer.allocateDirect(4 * WIDTH * HEIGHT - 1); - initializeRGBABuffer(rgba); - rgba.rewind(); - NativeI420Buffer i420 = NativeI420Buffer.allocate(WIDTH, HEIGHT); - assertThrows(RuntimeException.class, () -> { - VideoBufferConverter.convertToI420(rgba, i420, FourCC.RGBA); - }); - } - - @Test - void convertFromSmallNonDirectBufferToI420() throws Exception { - ByteBuffer rgba = ByteBuffer.allocate(4 * WIDTH * HEIGHT - 1); - initializeRGBABuffer(rgba); - rgba.rewind(); - NativeI420Buffer i420 = NativeI420Buffer.allocate(WIDTH, HEIGHT); - assertThrows(RuntimeException.class, () -> { - VideoBufferConverter.convertToI420(rgba, i420, FourCC.RGBA); - }); - } - - private void initializeI420Buffer(I420Buffer i420) { - ByteBuffer dataY = i420.getDataY(); - int strideY = i420.getStrideY(); - ByteBuffer dataU = i420.getDataU(); - int strideU = i420.getStrideU(); - ByteBuffer dataV = i420.getDataV(); - int strideV = i420.getStrideV(); - - byte value = 0; - for (int y = 0; y < HEIGHT; y++) { - for (int x = 0; x < WIDTH; x++) { - dataY.put(y * strideY + x, value++); - } - } - for (int y = 0; y < HEIGHT / 2; y++) { - for (int x = 0; x < WIDTH / 2; x++) { - dataU.put(y * strideU + x, value++); - dataV.put(y * strideV + x, value++); - } - } - } - - private void initializeRGBAArray(byte[] rgba) { - byte value = 0; - for (int i = 0; i < rgba.length; i++) { - rgba[i] = value++; - } - } - - private void initializeRGBABuffer(ByteBuffer rgba) { - byte value = 0; - for (int i = 0; i < rgba.limit(); i++) { - rgba.put(value++); - } - } - - private void verifyI420Buffer(I420Buffer i420, boolean expectingChanges) { - assertEquals(WIDTH, i420.getWidth()); - assertEquals(HEIGHT, i420.getHeight()); - - ByteBuffer dataY = i420.getDataY(); - int strideY = i420.getStrideY(); - ByteBuffer dataU = i420.getDataU(); - int strideU = i420.getStrideU(); - ByteBuffer dataV = i420.getDataV(); - int strideV = i420.getStrideV(); - - if (expectingChanges) { - boolean nonZeroY = false; - boolean nonZeroU = false; - boolean nonZeroV = false; - - for (int y = 0; y < HEIGHT; y++) { - for (int x = 0; x < WIDTH; x++) { - nonZeroY |= (dataY.get(y * strideY + x) != 0); - } - } - for (int y = 0; y < HEIGHT / 2; y++) { - for (int x = 0; x < WIDTH / 2; x++) { - nonZeroU |= (dataU.get(y * strideU + x) != 0); - nonZeroV |= (dataV.get(y * strideV + x) != 0); - } - } - - assertTrue(nonZeroY); - assertTrue(nonZeroU); - assertTrue(nonZeroV); - } - else { - byte value = 0; - for (int y = 0; y < HEIGHT; y++) { - for (int x = 0; x < WIDTH; x++) { - assertEquals(value++, dataY.get(y * strideY + x)); - } - } - for (int y = 0; y < HEIGHT / 2; y++) { - for (int x = 0; x < WIDTH / 2; x++) { - assertEquals(value++, dataU.get(y * strideU + x)); - assertEquals(value++, dataV.get(y * strideV + x)); - } - } - } - } - - private void verifyRGBAArray(byte[] rgba, boolean expectingChanges) { - assertEquals(4 * WIDTH * HEIGHT, rgba.length); - - if (expectingChanges) { - boolean nonZeroR = false; - boolean nonZeroG = false; - boolean nonZeroB = false; - - for (int i = 0; i < 4 * WIDTH * HEIGHT; i += 4) { - byte a = rgba[i + 0]; - byte b = rgba[i + 1]; - byte g = rgba[i + 2]; - byte r = rgba[i + 3]; - assertEquals((byte) -1, a); - nonZeroB |= (b != 0); - nonZeroG |= (g != 0); - nonZeroR |= (r != 0); - } - - assertTrue(nonZeroR); - assertTrue(nonZeroG); - assertTrue(nonZeroB); - } - else { - byte value = 0; - for (int i = 0; i < 4 * WIDTH * HEIGHT; i++) { - assertEquals(value++, rgba[i]); - } - } - } - - private void verifyRGBABuffer(ByteBuffer rgba, boolean expectingChanges) { - assertEquals(4 * WIDTH * HEIGHT, rgba.limit()); - - if (expectingChanges) { - boolean nonZeroR = false; - boolean nonZeroG = false; - boolean nonZeroB = false; - - for (int i = 0; i < 4 * WIDTH * HEIGHT; i += 4) { - byte a = rgba.get(); - byte b = rgba.get(); - byte g = rgba.get(); - byte r = rgba.get(); - assertEquals((byte) -1, a); - nonZeroB |= (b != 0); - nonZeroG |= (g != 0); - nonZeroR |= (r != 0); - } - - assertTrue(nonZeroR); - assertTrue(nonZeroG); - assertTrue(nonZeroB); - } - else { - byte value = 0; - for (int i = 0; i < 4 * WIDTH * HEIGHT; i++) { - assertEquals(value++, rgba.get()); - } - } - } - -} \ No newline at end of file diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/media/video/VideoTrackTests.java b/webrtc/src/test/java/dev/onvoid/webrtc/media/video/VideoTrackTests.java deleted file mode 100644 index 7c0d28a..0000000 --- a/webrtc/src/test/java/dev/onvoid/webrtc/media/video/VideoTrackTests.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.media.video; - -import static org.junit.jupiter.api.Assertions.*; - -import dev.onvoid.webrtc.TestBase; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class VideoTrackTests extends TestBase { - - private VideoTrack videoTrack; - - - @BeforeEach - void init() { - VideoDeviceSource videoSource = new VideoDeviceSource(); - - videoTrack = factory.createVideoTrack("videoTrack", videoSource); - } - - @AfterEach - void dispose() { - videoTrack.dispose(); - } - - @Test - void disableEnableTrack() { - videoTrack.setEnabled(false); - - assertFalse(videoTrack.isEnabled()); - - videoTrack.setEnabled(true); - - assertTrue(videoTrack.isEnabled()); - } - - @Test - void addNullSink() { - assertThrows(NullPointerException.class, () -> videoTrack.addSink(null)); - } - - @Test - void removeNullSink() { - assertThrows(NullPointerException.class, () -> videoTrack.removeSink(null)); - } - - @Test - void addRemoveSink() { - VideoTrackSink sink = frame -> { }; - - videoTrack.addSink(sink); - videoTrack.removeSink(sink); - } - -} From 52da4790359cabbe2455103e490c2791d2db1900 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Sat, 6 Dec 2025 22:30:55 -0800 Subject: [PATCH 02/81] Remove audio refs in JNI_PeerConnectionFactory --- .../src/main/cpp/include/JNI_PeerConnectionFactory.h | 8 -------- webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp | 6 ------ 2 files changed, 14 deletions(-) diff --git a/webrtc-jni/src/main/cpp/include/JNI_PeerConnectionFactory.h b/webrtc-jni/src/main/cpp/include/JNI_PeerConnectionFactory.h index 351bd93..162f437 100644 --- a/webrtc-jni/src/main/cpp/include/JNI_PeerConnectionFactory.h +++ b/webrtc-jni/src/main/cpp/include/JNI_PeerConnectionFactory.h @@ -24,14 +24,6 @@ extern "C" { JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_dispose (JNIEnv *, jobject); - /* - * Class: dev_onvoid_webrtc_PeerConnectionFactory - * Method: initialize - * Signature: (Ldev/onvoid/webrtc/media/audio/AudioDeviceModule;Ldev/onvoid/webrtc/media/audio/AudioProcessing;)V - */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_initialize - (JNIEnv *, jobject, jobject, jobject); - #ifdef __cplusplus } #endif diff --git a/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp b/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp index 33a1761..655b5fe 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp @@ -15,18 +15,12 @@ */ #include "JNI_PeerConnectionFactory.h" -#include "api/AudioOptions.h" -#include "api/CreateSessionDescriptionObserver.h" #include "api/PeerConnectionObserver.h" #include "api/RTCConfiguration.h" -#include "api/RTCRtpCapabilities.h" -#include "JavaEnums.h" #include "JavaError.h" #include "JavaFactories.h" #include "JavaNullPointerException.h" #include "JavaRuntimeException.h" -#include "JavaRef.h" -#include "JavaString.h" #include "JavaUtils.h" #include "api/create_peerconnection_factory.h" From 064e3730c9f6135c43536e6ca7eb8e04c1d3bd3c Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Sat, 6 Dec 2025 22:32:58 -0800 Subject: [PATCH 03/81] Remove more audio refs --- webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp b/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp index 655b5fe..f97b039 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp @@ -28,10 +28,6 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_initialize (JNIEnv * env, jobject caller) { - webrtc::AudioDeviceModule * audioDevModule = (audioModule != nullptr) - ? GetHandle(env, audioModule) - : nullptr; - try { auto networkThread = webrtc::Thread::CreateWithSocketServer(); networkThread->SetName("webrtc_jni_network_thread", nullptr); From ce16dabb62704d0656a905dde7fb51b1cefe0b50 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Sat, 6 Dec 2025 22:36:47 -0800 Subject: [PATCH 04/81] Remove media and desktop pkg refs from WebRTCContext --- webrtc-jni/src/main/cpp/src/WebRTCContext.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/webrtc-jni/src/main/cpp/src/WebRTCContext.cpp b/webrtc-jni/src/main/cpp/src/WebRTCContext.cpp index 7d66beb..4cd5e04 100644 --- a/webrtc-jni/src/main/cpp/src/WebRTCContext.cpp +++ b/webrtc-jni/src/main/cpp/src/WebRTCContext.cpp @@ -46,9 +46,7 @@ namespace jni } JavaEnums::add(env, PKG_LOG"Logging$Severity"); - JavaEnums::add(env, PKG_MEDIA"MediaType"); JavaEnums::add(env, PKG"RTCDataChannelState"); - JavaEnums::add(env, PKG_DESKTOP"DesktopCapturer$Result"); JavaEnums::add(env, PKG"RTCDtlsTransportState"); JavaEnums::add(env, PKG"RTCDtxStatus"); JavaEnums::add(env, PKG"RTCBundlePolicy"); From 36f08026afb8fc01dc749709d277b889bde97a29 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Sat, 6 Dec 2025 22:59:48 -0800 Subject: [PATCH 05/81] Fix macos arm and windows compile; Fix PeerConnectionFactory construct --- .../main/cpp/dependencies/webrtc/CMakeLists.txt | 4 ++-- .../onvoid/webrtc/PeerConnectionFactory.java | 17 +++++++++++------ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt index ac48c71..b56ad7d 100644 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt @@ -171,7 +171,7 @@ elseif(LINUX) target_compile_definitions(${PROJECT_NAME} PUBLIC WEBRTC_LINUX WEBRTC_POSIX) elseif(WIN32) target_compile_definitions(${PROJECT_NAME} PUBLIC WEBRTC_WIN NOMINMAX WIN32_LEAN_AND_MEAN NDEBUG) - target_link_libraries(${PROJECT_NAME} user32 iphlpapi secur32 ws2_32) + target_link_libraries(${PROJECT_NAME} user32 iphlpapi secur32 ws2_32 winmm dmoguids wmcodecdspuuid msdmo strmiids) endif() if(EXISTS "${WEBRTC_LIB_PATH}" OR EXISTS "${WEBRTC_LIB_PATH_INSTALLED}") @@ -286,7 +286,7 @@ execute_command( message(STATUS "WebRTC: compile") if(APPLE) execute_command( - COMMAND ninja -C "${WEBRTC_BUILD}" :default api/audio_codecs:builtin_audio_decoder_factory api/task_queue:default_task_queue_factory sdk:native_api sdk:default_codec_factory_objc pc:peer_connection sdk:videocapture_objc + COMMAND ninja -C "${WEBRTC_BUILD}" :default api/task_queue:default_task_queue_factory sdk:native_api pc:peer_connection WORKING_DIRECTORY "${WEBRTC_SRC}" ) diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/PeerConnectionFactory.java b/webrtc/src/main/java/dev/onvoid/webrtc/PeerConnectionFactory.java index 356e8b1..54f3259 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/PeerConnectionFactory.java +++ b/webrtc/src/main/java/dev/onvoid/webrtc/PeerConnectionFactory.java @@ -47,12 +47,12 @@ public class PeerConnectionFactory extends DisposableNativeObject { private long workerThreadHandle; - /** - * Creates an instance of PeerConnectionFactory. - */ - public PeerConnectionFactory() { - this(null, null); - } + /** + * Creates an instance of PeerConnectionFactory. + */ + public PeerConnectionFactory() { + initialize(); + } /** * Creates a new {@link RTCPeerConnection}. @@ -69,4 +69,9 @@ public native RTCPeerConnection createPeerConnection( @Override public native void dispose(); + /** + * Initializes the native PeerConnectionFactory. + */ + private native void initialize(); + } From b14b05cea2e51c9aca6ced26642a4f48db7b687d Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Sun, 7 Dec 2025 00:03:01 -0800 Subject: [PATCH 06/81] Fix macos compile and webrtc-examples module-info --- webrtc-examples/src/main/java/module-info.java | 1 - webrtc-jni/src/main/cpp/CMakeLists.txt | 2 +- webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/webrtc-examples/src/main/java/module-info.java b/webrtc-examples/src/main/java/module-info.java index b330984..4c3b296 100644 --- a/webrtc-examples/src/main/java/module-info.java +++ b/webrtc-examples/src/main/java/module-info.java @@ -8,7 +8,6 @@ requires webrtc.java; exports dev.onvoid.webrtc.examples.web.client; - exports dev.onvoid.webrtc.examples.web.server; exports dev.onvoid.webrtc.examples.web.model; } \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/CMakeLists.txt b/webrtc-jni/src/main/cpp/CMakeLists.txt index 8e8b7b3..4ae801f 100644 --- a/webrtc-jni/src/main/cpp/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/CMakeLists.txt @@ -83,7 +83,7 @@ target_link_libraries(${PROJECT_NAME} webrtc) if(APPLE) set_source_files_properties(${SOURCES} PROPERTIES COMPILE_FLAGS "-x objective-c++") target_link_options(${PROJECT_NAME} PRIVATE "-ObjC") - target_link_libraries(${PROJECT_NAME} "-framework Foundation" "-framework IOKit") + target_link_libraries(${PROJECT_NAME} "-framework Foundation" "-framework AVFoundation" "-framework CoreMedia" "-framework CoreAudio" "-framework IOKit" "-framework CoreVideo" "-framework VideoToolbox" "-framework QuartzCore") elseif(LINUX) if(NOT TARGET_CPU MATCHES "^arm") set(CXX_LIBS "-static-libgcc -stdlib=libc++ -lc++ -lc++abi") diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt index b56ad7d..21d1fc0 100644 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt @@ -165,7 +165,7 @@ if(APPLE) ${TARGET_INC_DIR}/sdk/objc/base ) target_compile_definitions(${PROJECT_NAME} PUBLIC WEBRTC_MAC WEBRTC_POSIX) - target_link_libraries(${PROJECT_NAME} "-framework Foundation" "-framework IOKit") + target_link_libraries(${PROJECT_NAME} "-framework Foundation" "-framework AVFoundation" "-framework CoreGraphics" "-framework CoreAudio" "-framework CoreVideo" "-framework ScreenCaptureKit" "-framework AudioToolbox" "-framework IOSurface" "-framework ApplicationServices" "-framework AppKit") elseif(LINUX) target_include_directories(${PROJECT_NAME} PUBLIC ${DBUS_INCLUDE_DIRS}) target_compile_definitions(${PROJECT_NAME} PUBLIC WEBRTC_LINUX WEBRTC_POSIX) From 01f5895418c83f1b38a988f1c449162782183693 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Sun, 7 Dec 2025 00:32:19 -0800 Subject: [PATCH 07/81] Add more compile flags --- .github/workflows/build.yml | 1 + webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8be3347..c22bf28 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,6 +8,7 @@ on: - "**.cpp" - "**.h" - "**.java" + - "**/CMakeLists.txt" pull_request: branches: diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt index 21d1fc0..15c248b 100644 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt @@ -266,7 +266,12 @@ symbol_level=0 \ rtc_use_x11=false \ use_dbus=false \ use_udev=false \ -rtc_use_pulseaudio=false") +rtc_use_pulseaudio=false \ +rtc_include_builtin_audio_codecs=false \ +rtc_include_opus=false \ +rtc_build_libvpx=false \ +rtc_disable_metrics=true \ +rtc_desktop_capture_supported=false") if(APPLE) set(COMPILE_ARGS "${COMPILE_ARGS} mac_deployment_target=\"${CMAKE_OSX_DEPLOYMENT_TARGET}\"") From faf63011e1f566356a9d7fd6cb8f95e3c7329d12 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Sun, 7 Dec 2025 13:36:45 -0800 Subject: [PATCH 08/81] Add header for JNI_PeerConnectionFactory#initialize --- .../src/main/cpp/include/JNI_PeerConnectionFactory.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/webrtc-jni/src/main/cpp/include/JNI_PeerConnectionFactory.h b/webrtc-jni/src/main/cpp/include/JNI_PeerConnectionFactory.h index 162f437..487ae19 100644 --- a/webrtc-jni/src/main/cpp/include/JNI_PeerConnectionFactory.h +++ b/webrtc-jni/src/main/cpp/include/JNI_PeerConnectionFactory.h @@ -24,6 +24,14 @@ extern "C" { JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_dispose (JNIEnv *, jobject); + /* + * Class: dev_onvoid_webrtc_PeerConnectionFactory + * Method: initialize + * Signature: ()V + */ + JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_initialize + (JNIEnv *, jobject); + #ifdef __cplusplus } #endif From a332c611644f1252b7eede8bc406f7c8c2416253 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Sun, 7 Dec 2025 14:28:51 -0800 Subject: [PATCH 09/81] Try creating dummy audio --- webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp b/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp index f97b039..90989fd 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp @@ -24,6 +24,7 @@ #include "JavaUtils.h" #include "api/create_peerconnection_factory.h" +#include "modules/audio_device/include/audio_device.h" JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_initialize (JNIEnv * env, jobject caller) @@ -48,11 +49,16 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_initialize throw jni::Exception("Start worker thread failed"); } + auto task_queue_factory = webrtc::CreateDefaultTaskQueueFactory(); + auto adm = webrtc::AudioDeviceModule::Create( + webrtc::AudioDeviceModule::kDummyAudio, + task_queue_factory.get()); + auto factory = webrtc::CreatePeerConnectionFactory( networkThread.get(), workerThread.get(), signalingThread.get(), - nullptr, // AudioDeviceModule + adm, // AudioDeviceModule nullptr, // AudioEncoderFactory nullptr, // AudioDecoderFactory nullptr, // VideoEncoderFactory From 2f28763d880f6213865c31f38a9101c29009de5b Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Sun, 7 Dec 2025 14:36:46 -0800 Subject: [PATCH 10/81] Imports --- webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp b/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp index 90989fd..b169325 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp @@ -24,6 +24,7 @@ #include "JavaUtils.h" #include "api/create_peerconnection_factory.h" +#include "api/task_queue/default_task_queue_factory.h" #include "modules/audio_device/include/audio_device.h" JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_initialize @@ -50,9 +51,12 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_initialize } auto task_queue_factory = webrtc::CreateDefaultTaskQueueFactory(); + auto task_queue_factory_ptr = task_queue_factory.release(); + auto adm = webrtc::AudioDeviceModule::Create( - webrtc::AudioDeviceModule::kDummyAudio, - task_queue_factory.get()); + webrtc::AudioDeviceModule::kDummyAudio, + task_queue_factory_ptr + ); auto factory = webrtc::CreatePeerConnectionFactory( networkThread.get(), From 269ecabdd7db62cc34bbf23ed8b886b774bb5cc6 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Sun, 7 Dec 2025 14:44:52 -0800 Subject: [PATCH 11/81] Import --- webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp b/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp index b169325..e9eef50 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp @@ -23,9 +23,9 @@ #include "JavaRuntimeException.h" #include "JavaUtils.h" -#include "api/create_peerconnection_factory.h" #include "api/task_queue/default_task_queue_factory.h" #include "modules/audio_device/include/audio_device.h" +#include "modules/audio_device/audio_device_impl.h" JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_initialize (JNIEnv * env, jobject caller) @@ -53,7 +53,7 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_initialize auto task_queue_factory = webrtc::CreateDefaultTaskQueueFactory(); auto task_queue_factory_ptr = task_queue_factory.release(); - auto adm = webrtc::AudioDeviceModule::Create( + auto adm = webrtc::AudioDeviceModuleImpl::Create( webrtc::AudioDeviceModule::kDummyAudio, task_queue_factory_ptr ); From 5b73bf1f7ace4e63b0ccc93e7a874fba9abbe9d3 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Sun, 7 Dec 2025 15:18:11 -0800 Subject: [PATCH 12/81] Imports --- .../include/api/HeadlessAudioDeviceModule.h | 181 +++++ .../cpp/src/JNI_PeerConnectionFactory.cpp | 68 +- .../cpp/src/api/HeadlessAudioDeviceModule.cpp | 637 ++++++++++++++++++ 3 files changed, 836 insertions(+), 50 deletions(-) create mode 100644 webrtc-jni/src/main/cpp/include/api/HeadlessAudioDeviceModule.h create mode 100644 webrtc-jni/src/main/cpp/src/api/HeadlessAudioDeviceModule.cpp diff --git a/webrtc-jni/src/main/cpp/include/api/HeadlessAudioDeviceModule.h b/webrtc-jni/src/main/cpp/include/api/HeadlessAudioDeviceModule.h new file mode 100644 index 0000000..58bb9b1 --- /dev/null +++ b/webrtc-jni/src/main/cpp/include/api/HeadlessAudioDeviceModule.h @@ -0,0 +1,181 @@ +/* + * Copyright 2019 Alex Andres + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JNI_WEBRTC_API_HEADLESS_ADM_H_ +#define JNI_WEBRTC_API_HEADLESS_ADM_H_ + +#include +#include +#include +#include +#include + +#include "api/environment/environment.h" +#include "api/environment/environment_factory.h" +#include "api/make_ref_counted.h" +#include "modules/audio_device/audio_device_buffer.h" +#include "modules/audio_device/include/audio_device.h" +#include "modules/audio_device/include/audio_device_defines.h" +#include "rtc_base/buffer.h" +#include "rtc_base/platform_thread.h" +#include "rtc_base/ref_counted_object.h" +#include "rtc_base/synchronization/mutex.h" +#include "rtc_base/thread.h" +#include "rtc_base/time_utils.h" + +namespace jni +{ + // A headless AudioDeviceModule that drives the render pipeline by pulling + // 10 ms PCM chunks from AudioTransport and discarding them, and simulates + // a microphone by pulling 10 ms PCM chunks from the registered AudioTransport + // and feeding them into the WebRTC capture pipeline. + class HeadlessAudioDeviceModule : public webrtc::AudioDeviceModule + { + public: + static webrtc::scoped_refptr Create( + const webrtc::Environment & env, + int sample_rate_hz = 48000, + size_t channels = 1) + { + return webrtc::make_ref_counted( + env, sample_rate_hz, channels); + } + + HeadlessAudioDeviceModule(const webrtc::Environment & env, int sample_rate_hz, size_t channels); + ~HeadlessAudioDeviceModule() override; + + // ----- AudioDeviceModule interface ----- + int32_t ActiveAudioLayer(webrtc::AudioDeviceModule::AudioLayer * audioLayer) const override; + int32_t RegisterAudioCallback(webrtc::AudioTransport * audioCallback) override; + int32_t Init() override; + int32_t Terminate() override; + bool Initialized() const override; + + // --- Device enumeration (stubbed; 1 virtual output device) --- + int16_t PlayoutDevices() override; + int16_t RecordingDevices() override; + int32_t PlayoutDeviceName(uint16_t index, + char name[webrtc::kAdmMaxDeviceNameSize], + char guid[webrtc::kAdmMaxGuidSize]) override; + int32_t RecordingDeviceName(uint16_t index, + char name[webrtc::kAdmMaxDeviceNameSize], + char guid[webrtc::kAdmMaxGuidSize]) override; + + // --- Device selection (recording not supported) --- + int32_t SetPlayoutDevice(uint16_t index) override; + int32_t SetPlayoutDevice(WindowsDeviceType device) override; + int32_t SetRecordingDevice(uint16_t index) override; + int32_t SetRecordingDevice(WindowsDeviceType device) override; + + // --- Audio transport initialization --- + int32_t PlayoutIsAvailable(bool * available) override; + int32_t InitPlayout() override; + bool PlayoutIsInitialized() const override; + int32_t RecordingIsAvailable(bool * available) override; + int32_t InitRecording() override; + bool RecordingIsInitialized() const override; + + // --- Audio transport control (playout only) --- + int32_t StartPlayout() override; + int32_t StopPlayout() override; + bool Playing() const override; + int32_t StartRecording() override; + int32_t StopRecording() override; + bool Recording() const override; + + // --- Mixer init (report success; nothing to init physically) --- + int32_t InitSpeaker() override; + bool SpeakerIsInitialized() const override; + int32_t InitMicrophone() override; + bool MicrophoneIsInitialized() const override; + + // --- Speaker volume (not supported) --- + int32_t SpeakerVolumeIsAvailable(bool * available) override; + int32_t SetSpeakerVolume(uint32_t volume) override; + int32_t SpeakerVolume(uint32_t * volume) const override; + int32_t MaxSpeakerVolume(uint32_t * maxVolume) const override; + int32_t MinSpeakerVolume(uint32_t * minVolume) const override; + + // --- Microphone volume (not supported) --- + int32_t MicrophoneVolumeIsAvailable(bool * available) override; + int32_t SetMicrophoneVolume(uint32_t volume) override; + int32_t MicrophoneVolume(uint32_t * volume) const override; + int32_t MaxMicrophoneVolume(uint32_t * maxVolume) const override; + int32_t MinMicrophoneVolume(uint32_t * minVolume) const override; + + // --- Mute controls (not supported) --- + int32_t SpeakerMuteIsAvailable(bool * available) override; + int32_t SetSpeakerMute(bool enable) override; + int32_t SpeakerMute(bool * enabled) const override; + int32_t MicrophoneMuteIsAvailable(bool * available) override; + int32_t SetMicrophoneMute(bool enable) override; + int32_t MicrophoneMute(bool * enabled) const override; + + // --- Stereo support (playout only) --- + int32_t StereoPlayoutIsAvailable(bool * available) const override; + int32_t SetStereoPlayout(bool enable) override; + int32_t StereoPlayout(bool * enabled) const override; + int32_t StereoRecordingIsAvailable(bool * available) const override; + int32_t SetStereoRecording(bool enable) override; + int32_t StereoRecording(bool * enabled) const override; + + // --- Playout delay (fixed, nominal) --- + int32_t PlayoutDelay(uint16_t * delayMS) const override; + + // --- Built-in effects (not supported here) --- + bool BuiltInAECIsAvailable() const override; + bool BuiltInAGCIsAvailable() const override; + bool BuiltInNSIsAvailable() const override; + int32_t EnableBuiltInAEC(bool enable) override; + int32_t EnableBuiltInAGC(bool enable) override; + int32_t EnableBuiltInNS(bool enable) override; + + // Android-only in real ADMs; just return 0 here. + int32_t GetPlayoutUnderrunCount() const override; + + private: + bool PlayThreadProcess(); + bool CaptureThreadProcess(); + + // State + bool initialized_ = false; + bool playout_initialized_ = false; + bool recording_initialized_ = false; + bool playing_ = false; + bool recording_ = false; + + // Format + int sample_rate_hz_ = 48000; + size_t channels_ = 1; + + webrtc::BufferT play_buffer_; + webrtc::BufferT record_buffer_; + + size_t playoutFramesIn10MS_; + size_t recordingFramesIn10MS_; + int64_t lastCallPlayoutMillis_; + int64_t lastCallRecordMillis_; + + mutable webrtc::Mutex mutex_; + std::unique_ptr audio_device_buffer_ RTC_GUARDED_BY(mutex_); + webrtc::AudioTransport * audio_callback_; + + webrtc::PlatformThread render_thread_; + webrtc::PlatformThread capture_thread_; + }; +} + +#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp b/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp index e9eef50..f8ae492 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp @@ -23,9 +23,9 @@ #include "JavaRuntimeException.h" #include "JavaUtils.h" -#include "api/task_queue/default_task_queue_factory.h" -#include "modules/audio_device/include/audio_device.h" -#include "modules/audio_device/audio_device_impl.h" +#include "api/create_peerconnection_factory.h" +#include "api/environment/environment_factory.h" +#include "api/HeadlessAudioDeviceModule.h" JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_initialize (JNIEnv * env, jobject caller) @@ -50,32 +50,24 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_initialize throw jni::Exception("Start worker thread failed"); } - auto task_queue_factory = webrtc::CreateDefaultTaskQueueFactory(); - auto task_queue_factory_ptr = task_queue_factory.release(); - - auto adm = webrtc::AudioDeviceModuleImpl::Create( - webrtc::AudioDeviceModule::kDummyAudio, - task_queue_factory_ptr - ); - - auto factory = webrtc::CreatePeerConnectionFactory( - networkThread.get(), - workerThread.get(), - signalingThread.get(), - adm, // AudioDeviceModule - nullptr, // AudioEncoderFactory - nullptr, // AudioDecoderFactory - nullptr, // VideoEncoderFactory - nullptr, // VideoDecoderFactory - nullptr, // AudioMixer - nullptr // AudioProcessing - ); + webrtc::EnvironmentFactory env_factory; + webrtc::Environment rtc_env = env_factory.Create(); + + auto adm = jni::HeadlessAudioDeviceModule::Create(rtc_env); + + webrtc::PeerConnectionFactoryDependencies dependencies; + dependencies.network_thread = networkThread.release(); + dependencies.worker_thread = workerThread.release(); + dependencies.signaling_thread = signalingThread.release(); + dependencies.adm = std::move(adm); + + auto factory = webrtc::CreateModularPeerConnectionFactory(std::move(dependencies)); if (factory != nullptr) { SetHandle(env, caller, factory.release()); - SetHandle(env, caller, "networkThreadHandle", networkThread.release()); - SetHandle(env, caller, "signalingThreadHandle", signalingThread.release()); - SetHandle(env, caller, "workerThreadHandle", workerThread.release()); + SetHandle(env, caller, "networkThreadHandle", nullptr); + SetHandle(env, caller, "signalingThreadHandle", nullptr); + SetHandle(env, caller, "workerThreadHandle", nullptr); } else { throw jni::Exception("Create PeerConnectionFactory failed"); @@ -92,10 +84,6 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_dispose webrtc::PeerConnectionFactoryInterface * factory = GetHandle(env, caller); CHECK_HANDLE(factory); - webrtc::Thread * networkThread = GetHandle(env, caller, "networkThreadHandle"); - webrtc::Thread * signalingThread = GetHandle(env, caller, "signalingThreadHandle"); - webrtc::Thread * workerThread = GetHandle(env, caller, "workerThreadHandle"); - webrtc::RefCountReleaseStatus status = factory->Release(); if (status != webrtc::RefCountReleaseStatus::kDroppedLastRef) { @@ -103,26 +91,6 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_dispose } SetHandle(env, caller, nullptr); - - factory = nullptr; - - try { - if (networkThread) { - networkThread->Stop(); - delete networkThread; - } - if (signalingThread) { - signalingThread->Stop(); - delete signalingThread; - } - if (workerThread) { - workerThread->Stop(); - delete workerThread; - } - } - catch (...) { - ThrowCxxJavaException(env); - } } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_createPeerConnection diff --git a/webrtc-jni/src/main/cpp/src/api/HeadlessAudioDeviceModule.cpp b/webrtc-jni/src/main/cpp/src/api/HeadlessAudioDeviceModule.cpp new file mode 100644 index 0000000..ddd560e --- /dev/null +++ b/webrtc-jni/src/main/cpp/src/api/HeadlessAudioDeviceModule.cpp @@ -0,0 +1,637 @@ +/* + * Copyright 2019 Alex Andres + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "api/HeadlessAudioDeviceModule.h" + +namespace jni +{ + HeadlessAudioDeviceModule::HeadlessAudioDeviceModule(const webrtc::Environment & env, + int sample_rate_hz, + size_t channels): + sample_rate_hz_(sample_rate_hz), + channels_(channels ? channels : 1), + playoutFramesIn10MS_(0), + recordingFramesIn10MS_(0), + lastCallPlayoutMillis_(0), + lastCallRecordMillis_(0), + audio_callback_(nullptr) + { + audio_device_buffer_ = std::make_unique(&env.task_queue_factory()); + } + + HeadlessAudioDeviceModule::~HeadlessAudioDeviceModule() + { + StopPlayout(); + StopRecording(); + } + + int32_t HeadlessAudioDeviceModule::ActiveAudioLayer(webrtc::AudioDeviceModule::AudioLayer * audioLayer) const + { + if (!audioLayer) { + return -1; + } + *audioLayer = kDummyAudio; + return 0; + } + + int32_t HeadlessAudioDeviceModule::RegisterAudioCallback(webrtc::AudioTransport * audioCallback) + { + webrtc::MutexLock lock(&mutex_); + audio_callback_ = audioCallback; + audio_device_buffer_->RegisterAudioCallback(audioCallback); + return 0; + } + + int32_t HeadlessAudioDeviceModule::Init() + { + initialized_ = true; + return 0; + } + + int32_t HeadlessAudioDeviceModule::Terminate() + { + StopPlayout(); + initialized_ = false; + return 0; + } + + bool HeadlessAudioDeviceModule::Initialized() const + { + return initialized_; + } + + int16_t HeadlessAudioDeviceModule::PlayoutDevices() + { + return 1; + } + + int16_t HeadlessAudioDeviceModule::RecordingDevices() + { + return 1; + } + + int32_t HeadlessAudioDeviceModule::PlayoutDeviceName(uint16_t index, + char name[webrtc::kAdmMaxDeviceNameSize], + char guid[webrtc::kAdmMaxGuidSize]) + { + if (index != 0) { + return -1; + } + + std::snprintf(name, webrtc::kAdmMaxDeviceNameSize, "Virtual Speaker (ADM)"); + std::snprintf(guid, webrtc::kAdmMaxGuidSize, "virtual-speaker"); + + return 0; + } + + int32_t HeadlessAudioDeviceModule::RecordingDeviceName(uint16_t index, + char name[webrtc::kAdmMaxDeviceNameSize], + char guid[webrtc::kAdmMaxGuidSize]) + { + if (index != 0) { + return -1; + } + std::snprintf(name, webrtc::kAdmMaxDeviceNameSize, "Virtual Microphone (ADM)"); + std::snprintf(guid, webrtc::kAdmMaxGuidSize, "virtual-microphone"); + return 0; + } + + int32_t HeadlessAudioDeviceModule::SetPlayoutDevice(uint16_t index) + { + return (index == 0) ? 0 : -1; + } + + int32_t HeadlessAudioDeviceModule::SetPlayoutDevice(WindowsDeviceType /*device*/) + { + return 0; + } + + int32_t HeadlessAudioDeviceModule::SetRecordingDevice(uint16_t index) + { + return (index == 0) ? 0 : -1; + } + + int32_t HeadlessAudioDeviceModule::SetRecordingDevice(WindowsDeviceType /*device*/) + { + return 0; + } + + int32_t HeadlessAudioDeviceModule::PlayoutIsAvailable(bool * available) + { + if (!available) { + return -1; + } + *available = true; + return 0; + } + + int32_t HeadlessAudioDeviceModule::InitPlayout() + { + if (!initialized_) { + return -1; + } + + playoutFramesIn10MS_ = static_cast(sample_rate_hz_ / 100); + + audio_device_buffer_->SetPlayoutSampleRate(static_cast(sample_rate_hz_)); + audio_device_buffer_->SetPlayoutChannels(static_cast(channels_)); + + const size_t total_samples = channels_ * playoutFramesIn10MS_; + if (play_buffer_.size() != total_samples) { + play_buffer_.SetSize(total_samples); + } + + playout_initialized_ = true; + return 0; + } + + bool HeadlessAudioDeviceModule::PlayoutIsInitialized() const + { + return playout_initialized_; + } + + int32_t HeadlessAudioDeviceModule::RecordingIsAvailable(bool * available) + { + if (!available) { + return -1; + } + *available = true; + return 0; + } + + int32_t HeadlessAudioDeviceModule::InitRecording() + { + if (!initialized_) { + return -1; + } + + recordingFramesIn10MS_ = static_cast(sample_rate_hz_ / 100); + + audio_device_buffer_->SetRecordingSampleRate(static_cast(sample_rate_hz_)); + audio_device_buffer_->SetRecordingChannels(static_cast(channels_)); + + const size_t total_samples = channels_ * recordingFramesIn10MS_; + if (record_buffer_.size() != total_samples) { + record_buffer_.SetSize(total_samples); + } + + recording_initialized_ = true; + return 0; + } + + bool HeadlessAudioDeviceModule::RecordingIsInitialized() const + { + return recording_initialized_; + } + + int32_t HeadlessAudioDeviceModule::StartPlayout() + { + if (!initialized_) { + return -1; + } + if (!playout_initialized_) { + return -1; + } + + { + webrtc::MutexLock lock(&mutex_); + if (playing_) { + return 0; // already playing + } + playing_ = true; + audio_device_buffer_->StartPlayout(); + } + + // Launch 10ms render pull thread. + render_thread_ = webrtc::PlatformThread::SpawnJoinable( + [this] { + while (PlayThreadProcess()) { + } + }, + "webrtc_audio_module_play_thread", + webrtc::ThreadAttributes().SetPriority(webrtc::ThreadPriority::kRealtime)); + + return 0; + } + + int32_t HeadlessAudioDeviceModule::StopPlayout() + { + { + webrtc::MutexLock lock(&mutex_); + if (!playing_) { + // Already stopped. + return 0; + } + playing_ = false; + } + + if (!render_thread_.empty()) { + render_thread_.Finalize(); + } + + { + webrtc::MutexLock lock(&mutex_); + audio_device_buffer_->StopPlayout(); + } + return 0; + } + + bool HeadlessAudioDeviceModule::Playing() const + { + return playing_; + } + + int32_t HeadlessAudioDeviceModule::StartRecording() + { + if (!initialized_) { + return -1; + } + if (!recording_initialized_) { + return -1; + } + + { + webrtc::MutexLock lock(&mutex_); + if (recording_) { + return 0; // already recording + } + recording_ = true; + audio_device_buffer_->StartRecording(); + } + + // Launch 10ms capture push thread. + capture_thread_ = webrtc::PlatformThread::SpawnJoinable( + [this] { + while (CaptureThreadProcess()) { + } + }, + "webrtc_audio_module_capture_thread", + webrtc::ThreadAttributes().SetPriority(webrtc::ThreadPriority::kRealtime)); + + return 0; + } + + int32_t HeadlessAudioDeviceModule::StopRecording() + { + { + webrtc::MutexLock lock(&mutex_); + if (!recording_) { + // Already stopped. + return 0; + } + recording_ = false; + } + + if (!capture_thread_.empty()) { + capture_thread_.Finalize(); + } + + { + webrtc::MutexLock lock(&mutex_); + audio_device_buffer_->StopRecording(); + } + return 0; + } + + bool HeadlessAudioDeviceModule::Recording() const + { + return recording_; + } + + int32_t HeadlessAudioDeviceModule::InitSpeaker() + { + return 0; + } + + bool HeadlessAudioDeviceModule::SpeakerIsInitialized() const + { + return true; + } + + int32_t HeadlessAudioDeviceModule::InitMicrophone() + { + return 0; + } + + bool HeadlessAudioDeviceModule::MicrophoneIsInitialized() const + { + return true; + } + + int32_t HeadlessAudioDeviceModule::SpeakerVolumeIsAvailable(bool * available) + { + if (!available) { + return -1; + } + *available = false; + return 0; + } + + int32_t HeadlessAudioDeviceModule::SetSpeakerVolume(uint32_t /*volume*/) + { + return -1; + } + + int32_t HeadlessAudioDeviceModule::SpeakerVolume(uint32_t * /*volume*/) const + { + return -1; + } + + int32_t HeadlessAudioDeviceModule::MaxSpeakerVolume(uint32_t * /*maxVolume*/) const + { + return -1; + } + + int32_t HeadlessAudioDeviceModule::MinSpeakerVolume(uint32_t * /*minVolume*/) const + { + return -1; + } + + int32_t HeadlessAudioDeviceModule::MicrophoneVolumeIsAvailable(bool * available) + { + if (!available) { + return -1; + } + *available = false; + return 0; + } + + int32_t HeadlessAudioDeviceModule::SetMicrophoneVolume(uint32_t /*volume*/) + { + return -1; + } + + int32_t HeadlessAudioDeviceModule::MicrophoneVolume(uint32_t * /*volume*/) const + { + return -1; + } + + int32_t HeadlessAudioDeviceModule::MaxMicrophoneVolume(uint32_t * /*maxVolume*/) const + { + return -1; + } + + int32_t HeadlessAudioDeviceModule::MinMicrophoneVolume(uint32_t * /*minVolume*/) const + { + return -1; + } + + int32_t HeadlessAudioDeviceModule::SpeakerMuteIsAvailable(bool * available) + { + if (!available) { + return -1; + } + *available = false; + return 0; + } + + int32_t HeadlessAudioDeviceModule::SetSpeakerMute(bool /*enable*/) + { + return -1; + } + + int32_t HeadlessAudioDeviceModule::SpeakerMute(bool * /*enabled*/) const + { + return -1; + } + + int32_t HeadlessAudioDeviceModule::MicrophoneMuteIsAvailable(bool * available) + { + if (!available) { + return -1; + } + *available = false; + return 0; + } + + int32_t HeadlessAudioDeviceModule::SetMicrophoneMute(bool /*enable*/) + { + return -1; + } + + int32_t HeadlessAudioDeviceModule::MicrophoneMute(bool * /*enabled*/) const + { + return -1; + } + + int32_t HeadlessAudioDeviceModule::StereoPlayoutIsAvailable(bool * available) const + { + if (!available) { + return -1; + } + *available = (channels_ >= 2); + return 0; + } + + int32_t HeadlessAudioDeviceModule::SetStereoPlayout(bool enable) + { + if (playout_initialized_) { + return -1; + } + + channels_ = enable ? 2u : 1u; + // Propagate channel change to AudioDeviceBuffer if playout is initialized. + webrtc::MutexLock lock(&mutex_); + + const size_t total_samples = channels_ * playoutFramesIn10MS_; + if (play_buffer_.size() != total_samples) { + play_buffer_.SetSize(total_samples); + } + + audio_device_buffer_->SetPlayoutChannels(static_cast(channels_)); + return 0; + } + + int32_t HeadlessAudioDeviceModule::StereoPlayout(bool * enabled) const + { + if (!enabled) { + return -1; + } + *enabled = (channels_ >= 2); + return 0; + } + + int32_t HeadlessAudioDeviceModule::StereoRecordingIsAvailable(bool * available) const + { + if (!available) { + return -1; + } + *available = (channels_ >= 2); + return 0; + } + + int32_t HeadlessAudioDeviceModule::SetStereoRecording(bool enable) + { + if (recording_initialized_) { + return -1; + } + channels_ = enable ? 2u : 1u; + webrtc::MutexLock lock(&mutex_); + const size_t total_samples = channels_ * recordingFramesIn10MS_; + if (record_buffer_.size() != total_samples) { + record_buffer_.SetSize(total_samples); + } + audio_device_buffer_->SetRecordingChannels(static_cast(channels_)); + return 0; + } + + int32_t HeadlessAudioDeviceModule::StereoRecording(bool * enabled) const + { + if (!enabled) { + return -1; + } + *enabled = (channels_ >= 2); + return 0; + } + + int32_t HeadlessAudioDeviceModule::PlayoutDelay(uint16_t * delayMS) const + { + if (!delayMS) { + return -1; + } + *delayMS = 50; // arbitrary nominal + return 0; + } + + bool HeadlessAudioDeviceModule::BuiltInAECIsAvailable() const + { + return false; + } + + bool HeadlessAudioDeviceModule::BuiltInAGCIsAvailable() const + { + return false; + } + + bool HeadlessAudioDeviceModule::BuiltInNSIsAvailable() const + { + return false; + } + + int32_t HeadlessAudioDeviceModule::EnableBuiltInAEC(bool /*enable*/) + { + return -1; + } + + int32_t HeadlessAudioDeviceModule::EnableBuiltInAGC(bool /*enable*/) + { + return -1; + } + + int32_t HeadlessAudioDeviceModule::EnableBuiltInNS(bool /*enable*/) + { + return -1; + } + + int32_t HeadlessAudioDeviceModule::GetPlayoutUnderrunCount() const + { + return 0; + } + + bool HeadlessAudioDeviceModule::PlayThreadProcess() + { + { + webrtc::MutexLock lock(&mutex_); + if (!playing_) { + return false; + } + } + + int64_t currentTime = webrtc::TimeMillis(); + mutex_.Lock(); + + if (lastCallPlayoutMillis_ == 0 || currentTime - lastCallPlayoutMillis_ >= 10) { + mutex_.Unlock(); + audio_device_buffer_->RequestPlayoutData(playoutFramesIn10MS_); + mutex_.Lock(); + + audio_device_buffer_->GetPlayoutData(play_buffer_.data()); + + lastCallPlayoutMillis_ = currentTime; + } + + mutex_.Unlock(); + + int64_t deltaTimeMillis = webrtc::TimeMillis() - currentTime; + + if (deltaTimeMillis < 10) { + webrtc::Thread::SleepMs(10 - deltaTimeMillis); + } + + return true; + } + + bool HeadlessAudioDeviceModule::CaptureThreadProcess() + { + webrtc::AudioTransport* callback = nullptr; + { + webrtc::MutexLock lock(&mutex_); + if (!recording_) { + return false; + } + callback = audio_callback_; + } + + int64_t currentTime = webrtc::TimeMillis(); + mutex_.Lock(); + + if (lastCallRecordMillis_ == 0 || currentTime - lastCallRecordMillis_ >= 10) { + size_t nSamplesOut = 0; + const size_t nBytesPerSample = sizeof(int16_t); + const size_t nChannels = channels_; + const uint32_t samplesPerSec = static_cast(sample_rate_hz_); + int64_t elapsed_time_ms = 0; + int64_t ntp_time_ms = 0; + + if (callback) { + // Pull 10 ms of audio from the registered AudioTransport (Java AudioSource). + callback->NeedMorePlayData(recordingFramesIn10MS_ * nChannels, + nBytesPerSample, + nChannels, + samplesPerSec, + record_buffer_.data(), + nSamplesOut, + &elapsed_time_ms, + &ntp_time_ms); + } + else { + nSamplesOut = recordingFramesIn10MS_ * nChannels; + std::memset(record_buffer_.data(), 0, nSamplesOut * nBytesPerSample); + } + + if (nChannels > 0) { + // Feed the captured buffer to WebRTC. + audio_device_buffer_->SetRecordedBuffer(record_buffer_.data(), recordingFramesIn10MS_); + audio_device_buffer_->SetVQEData(/*play_delay_ms*/ 0, /*rec_delay_ms*/ 0); + + lastCallRecordMillis_ = currentTime; + + mutex_.Unlock(); + audio_device_buffer_->DeliverRecordedData(); + mutex_.Lock(); + } + } + + mutex_.Unlock(); + + int64_t deltaTimeMillis = webrtc::TimeMillis() - currentTime; + if (deltaTimeMillis < 10) { + webrtc::Thread::SleepMs(10 - deltaTimeMillis); + } + + return true; + } +} From 81570e703cd31f41c8af25c011f8d1aa7e1403af Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Sun, 7 Dec 2025 15:30:46 -0800 Subject: [PATCH 13/81] Try CreateModularPeerConnectionFactory --- .../include/api/HeadlessAudioDeviceModule.h | 181 ----- .../cpp/src/JNI_PeerConnectionFactory.cpp | 36 +- .../cpp/src/api/HeadlessAudioDeviceModule.cpp | 637 ------------------ 3 files changed, 25 insertions(+), 829 deletions(-) delete mode 100644 webrtc-jni/src/main/cpp/include/api/HeadlessAudioDeviceModule.h delete mode 100644 webrtc-jni/src/main/cpp/src/api/HeadlessAudioDeviceModule.cpp diff --git a/webrtc-jni/src/main/cpp/include/api/HeadlessAudioDeviceModule.h b/webrtc-jni/src/main/cpp/include/api/HeadlessAudioDeviceModule.h deleted file mode 100644 index 58bb9b1..0000000 --- a/webrtc-jni/src/main/cpp/include/api/HeadlessAudioDeviceModule.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JNI_WEBRTC_API_HEADLESS_ADM_H_ -#define JNI_WEBRTC_API_HEADLESS_ADM_H_ - -#include -#include -#include -#include -#include - -#include "api/environment/environment.h" -#include "api/environment/environment_factory.h" -#include "api/make_ref_counted.h" -#include "modules/audio_device/audio_device_buffer.h" -#include "modules/audio_device/include/audio_device.h" -#include "modules/audio_device/include/audio_device_defines.h" -#include "rtc_base/buffer.h" -#include "rtc_base/platform_thread.h" -#include "rtc_base/ref_counted_object.h" -#include "rtc_base/synchronization/mutex.h" -#include "rtc_base/thread.h" -#include "rtc_base/time_utils.h" - -namespace jni -{ - // A headless AudioDeviceModule that drives the render pipeline by pulling - // 10 ms PCM chunks from AudioTransport and discarding them, and simulates - // a microphone by pulling 10 ms PCM chunks from the registered AudioTransport - // and feeding them into the WebRTC capture pipeline. - class HeadlessAudioDeviceModule : public webrtc::AudioDeviceModule - { - public: - static webrtc::scoped_refptr Create( - const webrtc::Environment & env, - int sample_rate_hz = 48000, - size_t channels = 1) - { - return webrtc::make_ref_counted( - env, sample_rate_hz, channels); - } - - HeadlessAudioDeviceModule(const webrtc::Environment & env, int sample_rate_hz, size_t channels); - ~HeadlessAudioDeviceModule() override; - - // ----- AudioDeviceModule interface ----- - int32_t ActiveAudioLayer(webrtc::AudioDeviceModule::AudioLayer * audioLayer) const override; - int32_t RegisterAudioCallback(webrtc::AudioTransport * audioCallback) override; - int32_t Init() override; - int32_t Terminate() override; - bool Initialized() const override; - - // --- Device enumeration (stubbed; 1 virtual output device) --- - int16_t PlayoutDevices() override; - int16_t RecordingDevices() override; - int32_t PlayoutDeviceName(uint16_t index, - char name[webrtc::kAdmMaxDeviceNameSize], - char guid[webrtc::kAdmMaxGuidSize]) override; - int32_t RecordingDeviceName(uint16_t index, - char name[webrtc::kAdmMaxDeviceNameSize], - char guid[webrtc::kAdmMaxGuidSize]) override; - - // --- Device selection (recording not supported) --- - int32_t SetPlayoutDevice(uint16_t index) override; - int32_t SetPlayoutDevice(WindowsDeviceType device) override; - int32_t SetRecordingDevice(uint16_t index) override; - int32_t SetRecordingDevice(WindowsDeviceType device) override; - - // --- Audio transport initialization --- - int32_t PlayoutIsAvailable(bool * available) override; - int32_t InitPlayout() override; - bool PlayoutIsInitialized() const override; - int32_t RecordingIsAvailable(bool * available) override; - int32_t InitRecording() override; - bool RecordingIsInitialized() const override; - - // --- Audio transport control (playout only) --- - int32_t StartPlayout() override; - int32_t StopPlayout() override; - bool Playing() const override; - int32_t StartRecording() override; - int32_t StopRecording() override; - bool Recording() const override; - - // --- Mixer init (report success; nothing to init physically) --- - int32_t InitSpeaker() override; - bool SpeakerIsInitialized() const override; - int32_t InitMicrophone() override; - bool MicrophoneIsInitialized() const override; - - // --- Speaker volume (not supported) --- - int32_t SpeakerVolumeIsAvailable(bool * available) override; - int32_t SetSpeakerVolume(uint32_t volume) override; - int32_t SpeakerVolume(uint32_t * volume) const override; - int32_t MaxSpeakerVolume(uint32_t * maxVolume) const override; - int32_t MinSpeakerVolume(uint32_t * minVolume) const override; - - // --- Microphone volume (not supported) --- - int32_t MicrophoneVolumeIsAvailable(bool * available) override; - int32_t SetMicrophoneVolume(uint32_t volume) override; - int32_t MicrophoneVolume(uint32_t * volume) const override; - int32_t MaxMicrophoneVolume(uint32_t * maxVolume) const override; - int32_t MinMicrophoneVolume(uint32_t * minVolume) const override; - - // --- Mute controls (not supported) --- - int32_t SpeakerMuteIsAvailable(bool * available) override; - int32_t SetSpeakerMute(bool enable) override; - int32_t SpeakerMute(bool * enabled) const override; - int32_t MicrophoneMuteIsAvailable(bool * available) override; - int32_t SetMicrophoneMute(bool enable) override; - int32_t MicrophoneMute(bool * enabled) const override; - - // --- Stereo support (playout only) --- - int32_t StereoPlayoutIsAvailable(bool * available) const override; - int32_t SetStereoPlayout(bool enable) override; - int32_t StereoPlayout(bool * enabled) const override; - int32_t StereoRecordingIsAvailable(bool * available) const override; - int32_t SetStereoRecording(bool enable) override; - int32_t StereoRecording(bool * enabled) const override; - - // --- Playout delay (fixed, nominal) --- - int32_t PlayoutDelay(uint16_t * delayMS) const override; - - // --- Built-in effects (not supported here) --- - bool BuiltInAECIsAvailable() const override; - bool BuiltInAGCIsAvailable() const override; - bool BuiltInNSIsAvailable() const override; - int32_t EnableBuiltInAEC(bool enable) override; - int32_t EnableBuiltInAGC(bool enable) override; - int32_t EnableBuiltInNS(bool enable) override; - - // Android-only in real ADMs; just return 0 here. - int32_t GetPlayoutUnderrunCount() const override; - - private: - bool PlayThreadProcess(); - bool CaptureThreadProcess(); - - // State - bool initialized_ = false; - bool playout_initialized_ = false; - bool recording_initialized_ = false; - bool playing_ = false; - bool recording_ = false; - - // Format - int sample_rate_hz_ = 48000; - size_t channels_ = 1; - - webrtc::BufferT play_buffer_; - webrtc::BufferT record_buffer_; - - size_t playoutFramesIn10MS_; - size_t recordingFramesIn10MS_; - int64_t lastCallPlayoutMillis_; - int64_t lastCallRecordMillis_; - - mutable webrtc::Mutex mutex_; - std::unique_ptr audio_device_buffer_ RTC_GUARDED_BY(mutex_); - webrtc::AudioTransport * audio_callback_; - - webrtc::PlatformThread render_thread_; - webrtc::PlatformThread capture_thread_; - }; -} - -#endif \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp b/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp index f8ae492..823a111 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp @@ -24,8 +24,6 @@ #include "JavaUtils.h" #include "api/create_peerconnection_factory.h" -#include "api/environment/environment_factory.h" -#include "api/HeadlessAudioDeviceModule.h" JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_initialize (JNIEnv * env, jobject caller) @@ -50,24 +48,16 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_initialize throw jni::Exception("Start worker thread failed"); } - webrtc::EnvironmentFactory env_factory; - webrtc::Environment rtc_env = env_factory.Create(); - - auto adm = jni::HeadlessAudioDeviceModule::Create(rtc_env); - webrtc::PeerConnectionFactoryDependencies dependencies; + dependencies.network_thread = networkThread.release(); dependencies.worker_thread = workerThread.release(); dependencies.signaling_thread = signalingThread.release(); - dependencies.adm = std::move(adm); auto factory = webrtc::CreateModularPeerConnectionFactory(std::move(dependencies)); if (factory != nullptr) { SetHandle(env, caller, factory.release()); - SetHandle(env, caller, "networkThreadHandle", nullptr); - SetHandle(env, caller, "signalingThreadHandle", nullptr); - SetHandle(env, caller, "workerThreadHandle", nullptr); } else { throw jni::Exception("Create PeerConnectionFactory failed"); @@ -84,6 +74,10 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_dispose webrtc::PeerConnectionFactoryInterface * factory = GetHandle(env, caller); CHECK_HANDLE(factory); + webrtc::Thread * networkThread = GetHandle(env, caller, "networkThreadHandle"); + webrtc::Thread * signalingThread = GetHandle(env, caller, "signalingThreadHandle"); + webrtc::Thread * workerThread = GetHandle(env, caller, "workerThreadHandle"); + webrtc::RefCountReleaseStatus status = factory->Release(); if (status != webrtc::RefCountReleaseStatus::kDroppedLastRef) { @@ -91,6 +85,26 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_dispose } SetHandle(env, caller, nullptr); + + factory = nullptr; + + try { + if (networkThread) { + networkThread->Stop(); + delete networkThread; + } + if (signalingThread) { + signalingThread->Stop(); + delete signalingThread; + } + if (workerThread) { + workerThread->Stop(); + delete workerThread; + } + } + catch (...) { + ThrowCxxJavaException(env); + } } JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_createPeerConnection diff --git a/webrtc-jni/src/main/cpp/src/api/HeadlessAudioDeviceModule.cpp b/webrtc-jni/src/main/cpp/src/api/HeadlessAudioDeviceModule.cpp deleted file mode 100644 index ddd560e..0000000 --- a/webrtc-jni/src/main/cpp/src/api/HeadlessAudioDeviceModule.cpp +++ /dev/null @@ -1,637 +0,0 @@ -/* - * Copyright 2019 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "api/HeadlessAudioDeviceModule.h" - -namespace jni -{ - HeadlessAudioDeviceModule::HeadlessAudioDeviceModule(const webrtc::Environment & env, - int sample_rate_hz, - size_t channels): - sample_rate_hz_(sample_rate_hz), - channels_(channels ? channels : 1), - playoutFramesIn10MS_(0), - recordingFramesIn10MS_(0), - lastCallPlayoutMillis_(0), - lastCallRecordMillis_(0), - audio_callback_(nullptr) - { - audio_device_buffer_ = std::make_unique(&env.task_queue_factory()); - } - - HeadlessAudioDeviceModule::~HeadlessAudioDeviceModule() - { - StopPlayout(); - StopRecording(); - } - - int32_t HeadlessAudioDeviceModule::ActiveAudioLayer(webrtc::AudioDeviceModule::AudioLayer * audioLayer) const - { - if (!audioLayer) { - return -1; - } - *audioLayer = kDummyAudio; - return 0; - } - - int32_t HeadlessAudioDeviceModule::RegisterAudioCallback(webrtc::AudioTransport * audioCallback) - { - webrtc::MutexLock lock(&mutex_); - audio_callback_ = audioCallback; - audio_device_buffer_->RegisterAudioCallback(audioCallback); - return 0; - } - - int32_t HeadlessAudioDeviceModule::Init() - { - initialized_ = true; - return 0; - } - - int32_t HeadlessAudioDeviceModule::Terminate() - { - StopPlayout(); - initialized_ = false; - return 0; - } - - bool HeadlessAudioDeviceModule::Initialized() const - { - return initialized_; - } - - int16_t HeadlessAudioDeviceModule::PlayoutDevices() - { - return 1; - } - - int16_t HeadlessAudioDeviceModule::RecordingDevices() - { - return 1; - } - - int32_t HeadlessAudioDeviceModule::PlayoutDeviceName(uint16_t index, - char name[webrtc::kAdmMaxDeviceNameSize], - char guid[webrtc::kAdmMaxGuidSize]) - { - if (index != 0) { - return -1; - } - - std::snprintf(name, webrtc::kAdmMaxDeviceNameSize, "Virtual Speaker (ADM)"); - std::snprintf(guid, webrtc::kAdmMaxGuidSize, "virtual-speaker"); - - return 0; - } - - int32_t HeadlessAudioDeviceModule::RecordingDeviceName(uint16_t index, - char name[webrtc::kAdmMaxDeviceNameSize], - char guid[webrtc::kAdmMaxGuidSize]) - { - if (index != 0) { - return -1; - } - std::snprintf(name, webrtc::kAdmMaxDeviceNameSize, "Virtual Microphone (ADM)"); - std::snprintf(guid, webrtc::kAdmMaxGuidSize, "virtual-microphone"); - return 0; - } - - int32_t HeadlessAudioDeviceModule::SetPlayoutDevice(uint16_t index) - { - return (index == 0) ? 0 : -1; - } - - int32_t HeadlessAudioDeviceModule::SetPlayoutDevice(WindowsDeviceType /*device*/) - { - return 0; - } - - int32_t HeadlessAudioDeviceModule::SetRecordingDevice(uint16_t index) - { - return (index == 0) ? 0 : -1; - } - - int32_t HeadlessAudioDeviceModule::SetRecordingDevice(WindowsDeviceType /*device*/) - { - return 0; - } - - int32_t HeadlessAudioDeviceModule::PlayoutIsAvailable(bool * available) - { - if (!available) { - return -1; - } - *available = true; - return 0; - } - - int32_t HeadlessAudioDeviceModule::InitPlayout() - { - if (!initialized_) { - return -1; - } - - playoutFramesIn10MS_ = static_cast(sample_rate_hz_ / 100); - - audio_device_buffer_->SetPlayoutSampleRate(static_cast(sample_rate_hz_)); - audio_device_buffer_->SetPlayoutChannels(static_cast(channels_)); - - const size_t total_samples = channels_ * playoutFramesIn10MS_; - if (play_buffer_.size() != total_samples) { - play_buffer_.SetSize(total_samples); - } - - playout_initialized_ = true; - return 0; - } - - bool HeadlessAudioDeviceModule::PlayoutIsInitialized() const - { - return playout_initialized_; - } - - int32_t HeadlessAudioDeviceModule::RecordingIsAvailable(bool * available) - { - if (!available) { - return -1; - } - *available = true; - return 0; - } - - int32_t HeadlessAudioDeviceModule::InitRecording() - { - if (!initialized_) { - return -1; - } - - recordingFramesIn10MS_ = static_cast(sample_rate_hz_ / 100); - - audio_device_buffer_->SetRecordingSampleRate(static_cast(sample_rate_hz_)); - audio_device_buffer_->SetRecordingChannels(static_cast(channels_)); - - const size_t total_samples = channels_ * recordingFramesIn10MS_; - if (record_buffer_.size() != total_samples) { - record_buffer_.SetSize(total_samples); - } - - recording_initialized_ = true; - return 0; - } - - bool HeadlessAudioDeviceModule::RecordingIsInitialized() const - { - return recording_initialized_; - } - - int32_t HeadlessAudioDeviceModule::StartPlayout() - { - if (!initialized_) { - return -1; - } - if (!playout_initialized_) { - return -1; - } - - { - webrtc::MutexLock lock(&mutex_); - if (playing_) { - return 0; // already playing - } - playing_ = true; - audio_device_buffer_->StartPlayout(); - } - - // Launch 10ms render pull thread. - render_thread_ = webrtc::PlatformThread::SpawnJoinable( - [this] { - while (PlayThreadProcess()) { - } - }, - "webrtc_audio_module_play_thread", - webrtc::ThreadAttributes().SetPriority(webrtc::ThreadPriority::kRealtime)); - - return 0; - } - - int32_t HeadlessAudioDeviceModule::StopPlayout() - { - { - webrtc::MutexLock lock(&mutex_); - if (!playing_) { - // Already stopped. - return 0; - } - playing_ = false; - } - - if (!render_thread_.empty()) { - render_thread_.Finalize(); - } - - { - webrtc::MutexLock lock(&mutex_); - audio_device_buffer_->StopPlayout(); - } - return 0; - } - - bool HeadlessAudioDeviceModule::Playing() const - { - return playing_; - } - - int32_t HeadlessAudioDeviceModule::StartRecording() - { - if (!initialized_) { - return -1; - } - if (!recording_initialized_) { - return -1; - } - - { - webrtc::MutexLock lock(&mutex_); - if (recording_) { - return 0; // already recording - } - recording_ = true; - audio_device_buffer_->StartRecording(); - } - - // Launch 10ms capture push thread. - capture_thread_ = webrtc::PlatformThread::SpawnJoinable( - [this] { - while (CaptureThreadProcess()) { - } - }, - "webrtc_audio_module_capture_thread", - webrtc::ThreadAttributes().SetPriority(webrtc::ThreadPriority::kRealtime)); - - return 0; - } - - int32_t HeadlessAudioDeviceModule::StopRecording() - { - { - webrtc::MutexLock lock(&mutex_); - if (!recording_) { - // Already stopped. - return 0; - } - recording_ = false; - } - - if (!capture_thread_.empty()) { - capture_thread_.Finalize(); - } - - { - webrtc::MutexLock lock(&mutex_); - audio_device_buffer_->StopRecording(); - } - return 0; - } - - bool HeadlessAudioDeviceModule::Recording() const - { - return recording_; - } - - int32_t HeadlessAudioDeviceModule::InitSpeaker() - { - return 0; - } - - bool HeadlessAudioDeviceModule::SpeakerIsInitialized() const - { - return true; - } - - int32_t HeadlessAudioDeviceModule::InitMicrophone() - { - return 0; - } - - bool HeadlessAudioDeviceModule::MicrophoneIsInitialized() const - { - return true; - } - - int32_t HeadlessAudioDeviceModule::SpeakerVolumeIsAvailable(bool * available) - { - if (!available) { - return -1; - } - *available = false; - return 0; - } - - int32_t HeadlessAudioDeviceModule::SetSpeakerVolume(uint32_t /*volume*/) - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::SpeakerVolume(uint32_t * /*volume*/) const - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::MaxSpeakerVolume(uint32_t * /*maxVolume*/) const - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::MinSpeakerVolume(uint32_t * /*minVolume*/) const - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::MicrophoneVolumeIsAvailable(bool * available) - { - if (!available) { - return -1; - } - *available = false; - return 0; - } - - int32_t HeadlessAudioDeviceModule::SetMicrophoneVolume(uint32_t /*volume*/) - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::MicrophoneVolume(uint32_t * /*volume*/) const - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::MaxMicrophoneVolume(uint32_t * /*maxVolume*/) const - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::MinMicrophoneVolume(uint32_t * /*minVolume*/) const - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::SpeakerMuteIsAvailable(bool * available) - { - if (!available) { - return -1; - } - *available = false; - return 0; - } - - int32_t HeadlessAudioDeviceModule::SetSpeakerMute(bool /*enable*/) - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::SpeakerMute(bool * /*enabled*/) const - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::MicrophoneMuteIsAvailable(bool * available) - { - if (!available) { - return -1; - } - *available = false; - return 0; - } - - int32_t HeadlessAudioDeviceModule::SetMicrophoneMute(bool /*enable*/) - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::MicrophoneMute(bool * /*enabled*/) const - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::StereoPlayoutIsAvailable(bool * available) const - { - if (!available) { - return -1; - } - *available = (channels_ >= 2); - return 0; - } - - int32_t HeadlessAudioDeviceModule::SetStereoPlayout(bool enable) - { - if (playout_initialized_) { - return -1; - } - - channels_ = enable ? 2u : 1u; - // Propagate channel change to AudioDeviceBuffer if playout is initialized. - webrtc::MutexLock lock(&mutex_); - - const size_t total_samples = channels_ * playoutFramesIn10MS_; - if (play_buffer_.size() != total_samples) { - play_buffer_.SetSize(total_samples); - } - - audio_device_buffer_->SetPlayoutChannels(static_cast(channels_)); - return 0; - } - - int32_t HeadlessAudioDeviceModule::StereoPlayout(bool * enabled) const - { - if (!enabled) { - return -1; - } - *enabled = (channels_ >= 2); - return 0; - } - - int32_t HeadlessAudioDeviceModule::StereoRecordingIsAvailable(bool * available) const - { - if (!available) { - return -1; - } - *available = (channels_ >= 2); - return 0; - } - - int32_t HeadlessAudioDeviceModule::SetStereoRecording(bool enable) - { - if (recording_initialized_) { - return -1; - } - channels_ = enable ? 2u : 1u; - webrtc::MutexLock lock(&mutex_); - const size_t total_samples = channels_ * recordingFramesIn10MS_; - if (record_buffer_.size() != total_samples) { - record_buffer_.SetSize(total_samples); - } - audio_device_buffer_->SetRecordingChannels(static_cast(channels_)); - return 0; - } - - int32_t HeadlessAudioDeviceModule::StereoRecording(bool * enabled) const - { - if (!enabled) { - return -1; - } - *enabled = (channels_ >= 2); - return 0; - } - - int32_t HeadlessAudioDeviceModule::PlayoutDelay(uint16_t * delayMS) const - { - if (!delayMS) { - return -1; - } - *delayMS = 50; // arbitrary nominal - return 0; - } - - bool HeadlessAudioDeviceModule::BuiltInAECIsAvailable() const - { - return false; - } - - bool HeadlessAudioDeviceModule::BuiltInAGCIsAvailable() const - { - return false; - } - - bool HeadlessAudioDeviceModule::BuiltInNSIsAvailable() const - { - return false; - } - - int32_t HeadlessAudioDeviceModule::EnableBuiltInAEC(bool /*enable*/) - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::EnableBuiltInAGC(bool /*enable*/) - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::EnableBuiltInNS(bool /*enable*/) - { - return -1; - } - - int32_t HeadlessAudioDeviceModule::GetPlayoutUnderrunCount() const - { - return 0; - } - - bool HeadlessAudioDeviceModule::PlayThreadProcess() - { - { - webrtc::MutexLock lock(&mutex_); - if (!playing_) { - return false; - } - } - - int64_t currentTime = webrtc::TimeMillis(); - mutex_.Lock(); - - if (lastCallPlayoutMillis_ == 0 || currentTime - lastCallPlayoutMillis_ >= 10) { - mutex_.Unlock(); - audio_device_buffer_->RequestPlayoutData(playoutFramesIn10MS_); - mutex_.Lock(); - - audio_device_buffer_->GetPlayoutData(play_buffer_.data()); - - lastCallPlayoutMillis_ = currentTime; - } - - mutex_.Unlock(); - - int64_t deltaTimeMillis = webrtc::TimeMillis() - currentTime; - - if (deltaTimeMillis < 10) { - webrtc::Thread::SleepMs(10 - deltaTimeMillis); - } - - return true; - } - - bool HeadlessAudioDeviceModule::CaptureThreadProcess() - { - webrtc::AudioTransport* callback = nullptr; - { - webrtc::MutexLock lock(&mutex_); - if (!recording_) { - return false; - } - callback = audio_callback_; - } - - int64_t currentTime = webrtc::TimeMillis(); - mutex_.Lock(); - - if (lastCallRecordMillis_ == 0 || currentTime - lastCallRecordMillis_ >= 10) { - size_t nSamplesOut = 0; - const size_t nBytesPerSample = sizeof(int16_t); - const size_t nChannels = channels_; - const uint32_t samplesPerSec = static_cast(sample_rate_hz_); - int64_t elapsed_time_ms = 0; - int64_t ntp_time_ms = 0; - - if (callback) { - // Pull 10 ms of audio from the registered AudioTransport (Java AudioSource). - callback->NeedMorePlayData(recordingFramesIn10MS_ * nChannels, - nBytesPerSample, - nChannels, - samplesPerSec, - record_buffer_.data(), - nSamplesOut, - &elapsed_time_ms, - &ntp_time_ms); - } - else { - nSamplesOut = recordingFramesIn10MS_ * nChannels; - std::memset(record_buffer_.data(), 0, nSamplesOut * nBytesPerSample); - } - - if (nChannels > 0) { - // Feed the captured buffer to WebRTC. - audio_device_buffer_->SetRecordedBuffer(record_buffer_.data(), recordingFramesIn10MS_); - audio_device_buffer_->SetVQEData(/*play_delay_ms*/ 0, /*rec_delay_ms*/ 0); - - lastCallRecordMillis_ = currentTime; - - mutex_.Unlock(); - audio_device_buffer_->DeliverRecordedData(); - mutex_.Lock(); - } - } - - mutex_.Unlock(); - - int64_t deltaTimeMillis = webrtc::TimeMillis() - currentTime; - if (deltaTimeMillis < 10) { - webrtc::Thread::SleepMs(10 - deltaTimeMillis); - } - - return true; - } -} From cd568698666552c6783449c186da413bd413a623 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Sun, 7 Dec 2025 17:20:33 -0800 Subject: [PATCH 14/81] Modify webrtc comp args --- .../cpp/dependencies/webrtc/CMakeLists.txt | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt index 15c248b..4c3c806 100644 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt @@ -253,25 +253,34 @@ is_clang=true \ is_debug=false \ is_component_build=false \ treat_warnings_as_errors=false \ +rtc_include_ilbc=false \ +rtc_include_opus=false \ +rtc_opus_support_120ms_ptime=false \ +rtc_opus_variable_complexity=false \ +rtc_exclude_audio_processing_module=true \ rtc_build_tools=false \ -rtc_use_perfetto=false \ +rtc_build_examples=false \ +rtc_use_x11=false \ rtc_use_pipewire=false \ +rtc_link_pipewire=false \ +rtc_use_h264=false \ +rtc_include_builtin_audio_codecs=false \ +rtc_include_builtin_video_codecs=false \ +rtc_build_libvpx=false \ +rtc_build_opus=false \ +rtc_libvpx_build_vp9=false \ +rtc_include_pulse_audio=false \ +rtc_include_internal_audio_device=false \ +rtc_desktop_capture_supported=false \ +rtc_use_perfetto=false \ rtc_enable_protobuf=false \ -rtc_build_examples=false \ rtc_include_tests=false \ use_rtti=true \ -rtc_use_h264=false \ -ffmpeg_branding=\"Chrome\" \ symbol_level=0 \ -rtc_use_x11=false \ use_dbus=false \ use_udev=false \ rtc_use_pulseaudio=false \ -rtc_include_builtin_audio_codecs=false \ -rtc_include_opus=false \ -rtc_build_libvpx=false \ -rtc_disable_metrics=true \ -rtc_desktop_capture_supported=false") +rtc_disable_metrics=true") if(APPLE) set(COMPILE_ARGS "${COMPILE_ARGS} mac_deployment_target=\"${CMAKE_OSX_DEPLOYMENT_TARGET}\"") From df4d84081266d7547e0dfb513c55bc62397179c8 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Sun, 7 Dec 2025 17:30:24 -0800 Subject: [PATCH 15/81] Decrease chance of test hang --- .../webrtc/PortAllocatorConfigIntegrationTest.java | 4 ++-- .../dev/onvoid/webrtc/logging/LoggingTests.java | 13 +++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/PortAllocatorConfigIntegrationTest.java b/webrtc/src/test/java/dev/onvoid/webrtc/PortAllocatorConfigIntegrationTest.java index d97cc68..e84a624 100644 --- a/webrtc/src/test/java/dev/onvoid/webrtc/PortAllocatorConfigIntegrationTest.java +++ b/webrtc/src/test/java/dev/onvoid/webrtc/PortAllocatorConfigIntegrationTest.java @@ -35,8 +35,8 @@ class PortAllocatorConfigIntegrationTest extends TestBase { @Test void iceCandidatesRespectPortAllocatorConfig() throws Exception { // Constrain ephemeral port range and disable TCP candidates. - int minPort = 48000; - int maxPort = 48050; + int minPort = 50000; + int maxPort = 50200; RTCConfiguration cfg = new RTCConfiguration(); cfg.portAllocatorConfig.minPort = minPort; diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/logging/LoggingTests.java b/webrtc/src/test/java/dev/onvoid/webrtc/logging/LoggingTests.java index 2e1a247..fa4d308 100644 --- a/webrtc/src/test/java/dev/onvoid/webrtc/logging/LoggingTests.java +++ b/webrtc/src/test/java/dev/onvoid/webrtc/logging/LoggingTests.java @@ -29,20 +29,21 @@ class LoggingTests { @Test void logInfo() throws Exception { - CountDownLatch latch = new CountDownLatch(3); + CountDownLatch latch = new CountDownLatch(1); LogSink sink = (severity, message) -> { - assertTrue(severity.ordinal() > Severity.VERBOSE.ordinal()); - assertNotNull(message); - - latch.countDown(); + if (severity.ordinal() > Severity.VERBOSE.ordinal() && message != null) { + latch.countDown(); + } }; Logging.addLogSink(Logging.Severity.INFO, sink); PeerConnectionFactory factory = new PeerConnectionFactory(); - latch.await(); + Logging.info("Test log message"); + + assertTrue(latch.await(5, TimeUnit.SECONDS), "Did not receive log message"); factory.dispose(); } From 515a02ffba229d169ca706cbddd8819f6d12edbd Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Sun, 7 Dec 2025 18:22:47 -0800 Subject: [PATCH 16/81] Fix missing time import for test --- webrtc/src/test/java/dev/onvoid/webrtc/logging/LoggingTests.java | 1 + 1 file changed, 1 insertion(+) diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/logging/LoggingTests.java b/webrtc/src/test/java/dev/onvoid/webrtc/logging/LoggingTests.java index fa4d308..17efc9a 100644 --- a/webrtc/src/test/java/dev/onvoid/webrtc/logging/LoggingTests.java +++ b/webrtc/src/test/java/dev/onvoid/webrtc/logging/LoggingTests.java @@ -19,6 +19,7 @@ import static org.junit.jupiter.api.Assertions.*; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import dev.onvoid.webrtc.PeerConnectionFactory; import dev.onvoid.webrtc.logging.Logging.Severity; From 2822ae2211a4acb2f605ff31905ae683bde78ae1 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Sun, 7 Dec 2025 19:12:19 -0800 Subject: [PATCH 17/81] Wait until RTCIceGatheringState.COMPLETE instead of connect --- .../PortAllocatorConfigIntegrationTest.java | 38 +++++++++---------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/PortAllocatorConfigIntegrationTest.java b/webrtc/src/test/java/dev/onvoid/webrtc/PortAllocatorConfigIntegrationTest.java index e84a624..67ffba4 100644 --- a/webrtc/src/test/java/dev/onvoid/webrtc/PortAllocatorConfigIntegrationTest.java +++ b/webrtc/src/test/java/dev/onvoid/webrtc/PortAllocatorConfigIntegrationTest.java @@ -35,8 +35,8 @@ class PortAllocatorConfigIntegrationTest extends TestBase { @Test void iceCandidatesRespectPortAllocatorConfig() throws Exception { // Constrain ephemeral port range and disable TCP candidates. - int minPort = 50000; - int maxPort = 50200; + int minPort = 50000; + int maxPort = 50200; RTCConfiguration cfg = new RTCConfiguration(); cfg.portAllocatorConfig.minPort = minPort; @@ -60,12 +60,10 @@ void iceCandidatesRespectPortAllocatorConfig() throws Exception { callee.setRemoteDescription(caller.createOffer()); caller.setRemoteDescription(callee.createAnswer()); - // Wait until connected (with a timeout to avoid hanging tests). - assertTrue(caller.awaitConnected(30, TimeUnit.SECONDS), "Caller failed to connect in time"); - assertTrue(callee.awaitConnected(30, TimeUnit.SECONDS), "Callee failed to connect in time"); - - // Give ICE gathering a brief moment. - Thread.sleep(500); + // Wait until ICE gathering is complete. This verifies the allocator works + // without depending on successful connection establishment which can be flaky in CI/restricted envs. + assertTrue(caller.awaitGatheringComplete(30, TimeUnit.SECONDS), "Caller gathering timed out"); + assertTrue(callee.awaitGatheringComplete(30, TimeUnit.SECONDS), "Callee gathering timed out"); // Basic expectations: Some candidates gathered on both sides. assertFalse(caller.candidates.isEmpty(), "Caller gathered no ICE candidates"); @@ -74,22 +72,22 @@ void iceCandidatesRespectPortAllocatorConfig() throws Exception { // Check protocol and port range for HOST candidates. for (String c : caller.candidates) { assertFalse(c.contains(" tcp ") || c.contains(" tcp\n"), - "TCP candidate appeared despite TCP being disabled: " + c); + "TCP candidate appeared despite TCP being disabled: " + c); - if (c.contains(" typ host")) { + if (c.contains(" typ host")) { int port = parsePortFromCandidate(c); assertTrue(port >= minPort && port <= maxPort, - "Host candidate port out of range: " + port + " in " + c); + "Host candidate port out of range: " + port + " in " + c); } } for (String c : callee.candidates) { assertFalse(c.contains(" tcp ") || c.contains(" tcp\n"), - "TCP candidate appeared despite TCP being disabled: " + c); + "TCP candidate appeared despite TCP being disabled: " + c); - if (c.contains(" typ host")) { + if (c.contains(" typ host")) { int port = parsePortFromCandidate(c); assertTrue(port >= minPort && port <= maxPort, - "Host candidate port out of range: " + port + " in " + c); + "Host candidate port out of range: " + port + " in " + c); } } @@ -117,7 +115,7 @@ private static class AllocPeer implements PeerConnectionObserver { private final RTCPeerConnection pc; private RTCPeerConnection remote; - private final CountDownLatch connected = new CountDownLatch(1); + private final CountDownLatch gatheringComplete = new CountDownLatch(1); final List candidates = new ArrayList<>(); @@ -157,8 +155,8 @@ void setRemoteDescription(RTCSessionDescription description) throws Exception { set.get(); } - boolean awaitConnected(long timeout, TimeUnit unit) throws InterruptedException { - return connected.await(timeout, unit); + boolean awaitGatheringComplete(long timeout, TimeUnit unit) throws InterruptedException { + return gatheringComplete.await(timeout, unit); } void close() { @@ -174,9 +172,9 @@ public void onIceCandidate(RTCIceCandidate candidate) { } @Override - public void onConnectionChange(RTCPeerConnectionState state) { - if (state == RTCPeerConnectionState.CONNECTED) { - connected.countDown(); + public void onIceGatheringChange(RTCIceGatheringState state) { + if (state == RTCIceGatheringState.COMPLETE) { + gatheringComplete.countDown(); } } } From fb3d89dc4f7d05535836b206ef68d3d8656d2380 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Sun, 7 Dec 2025 23:29:37 -0800 Subject: [PATCH 18/81] Further slim webrtc build --- webrtc-jni/src/main/cpp/CMakeLists.txt | 4 ++-- .../cpp/dependencies/webrtc/CMakeLists.txt | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/webrtc-jni/src/main/cpp/CMakeLists.txt b/webrtc-jni/src/main/cpp/CMakeLists.txt index 4ae801f..65a9052 100644 --- a/webrtc-jni/src/main/cpp/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/CMakeLists.txt @@ -83,7 +83,7 @@ target_link_libraries(${PROJECT_NAME} webrtc) if(APPLE) set_source_files_properties(${SOURCES} PROPERTIES COMPILE_FLAGS "-x objective-c++") target_link_options(${PROJECT_NAME} PRIVATE "-ObjC") - target_link_libraries(${PROJECT_NAME} "-framework Foundation" "-framework AVFoundation" "-framework CoreMedia" "-framework CoreAudio" "-framework IOKit" "-framework CoreVideo" "-framework VideoToolbox" "-framework QuartzCore") + target_link_libraries(${PROJECT_NAME} "-framework Foundation") elseif(LINUX) if(NOT TARGET_CPU MATCHES "^arm") set(CXX_LIBS "-static-libgcc -stdlib=libc++ -lc++ -lc++abi") @@ -93,7 +93,7 @@ elseif(LINUX) target_link_libraries(${PROJECT_NAME} ${CXX_LIBS}) elseif(WIN32) - target_link_libraries(${PROJECT_NAME} shcore.lib) + target_link_libraries(${PROJECT_NAME}) endif() install(TARGETS ${PROJECT_NAME} diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt index 4c3c806..6ca4f97 100644 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt @@ -154,7 +154,6 @@ target_include_directories(${PROJECT_NAME} PUBLIC ${TARGET_INC_DIR} ${TARGET_INC_DIR}/third_party/abseil-cpp - ${TARGET_INC_DIR}/third_party/libyuv/include ) target_link_libraries(${PROJECT_NAME} ${TARGET_LINK_LIB}) @@ -165,13 +164,13 @@ if(APPLE) ${TARGET_INC_DIR}/sdk/objc/base ) target_compile_definitions(${PROJECT_NAME} PUBLIC WEBRTC_MAC WEBRTC_POSIX) - target_link_libraries(${PROJECT_NAME} "-framework Foundation" "-framework AVFoundation" "-framework CoreGraphics" "-framework CoreAudio" "-framework CoreVideo" "-framework ScreenCaptureKit" "-framework AudioToolbox" "-framework IOSurface" "-framework ApplicationServices" "-framework AppKit") + target_link_libraries(${PROJECT_NAME} "-framework Foundation") elseif(LINUX) - target_include_directories(${PROJECT_NAME} PUBLIC ${DBUS_INCLUDE_DIRS}) + target_include_directories(${PROJECT_NAME} PUBLIC) target_compile_definitions(${PROJECT_NAME} PUBLIC WEBRTC_LINUX WEBRTC_POSIX) elseif(WIN32) target_compile_definitions(${PROJECT_NAME} PUBLIC WEBRTC_WIN NOMINMAX WIN32_LEAN_AND_MEAN NDEBUG) - target_link_libraries(${PROJECT_NAME} user32 iphlpapi secur32 ws2_32 winmm dmoguids wmcodecdspuuid msdmo strmiids) + target_link_libraries(${PROJECT_NAME} user32 iphlpapi secur32 ws2_32) endif() if(EXISTS "${WEBRTC_LIB_PATH}" OR EXISTS "${WEBRTC_LIB_PATH_INSTALLED}") @@ -261,26 +260,33 @@ rtc_exclude_audio_processing_module=true \ rtc_build_tools=false \ rtc_build_examples=false \ rtc_use_x11=false \ +rtc_use_x11_extensions=false \ rtc_use_pipewire=false \ rtc_link_pipewire=false \ rtc_use_h264=false \ rtc_include_builtin_audio_codecs=false \ rtc_include_builtin_video_codecs=false \ +rtc_enable_win_wgc=false \ rtc_build_libvpx=false \ rtc_build_opus=false \ rtc_libvpx_build_vp9=false \ rtc_include_pulse_audio=false \ rtc_include_internal_audio_device=false \ -rtc_desktop_capture_supported=false \ rtc_use_perfetto=false \ rtc_enable_protobuf=false \ rtc_include_tests=false \ +rtc_use_gtk=false \ +rtc_build_libjpeg=false \ +rtc_build_openmax_dl=false \ +rtc_build_libyuv=false \ +rtc_include_dav1d_in_internal_decoder_factory=false \ use_rtti=true \ symbol_level=0 \ use_dbus=false \ use_udev=false \ rtc_use_pulseaudio=false \ -rtc_disable_metrics=true") +rtc_disable_metrics=true \ +proprietary_codecs=false") if(APPLE) set(COMPILE_ARGS "${COMPILE_ARGS} mac_deployment_target=\"${CMAKE_OSX_DEPLOYMENT_TARGET}\"") From 2736c0afc8114e4b36c7765b38262421dccc8321 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Mon, 8 Dec 2025 00:32:33 -0800 Subject: [PATCH 19/81] Force disable desktop capture on mac and windows --- .../src/main/cpp/dependencies/webrtc/CMakeLists.txt | 1 - .../webrtc/patches/macos/disable_desktop_capture.patch | 8 ++++++++ .../webrtc/patches/windows/disable_desktop_capture.patch | 8 ++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 webrtc-jni/src/main/cpp/dependencies/webrtc/patches/macos/disable_desktop_capture.patch create mode 100644 webrtc-jni/src/main/cpp/dependencies/webrtc/patches/windows/disable_desktop_capture.patch diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt index 6ca4f97..5cead18 100644 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt @@ -276,7 +276,6 @@ rtc_use_perfetto=false \ rtc_enable_protobuf=false \ rtc_include_tests=false \ rtc_use_gtk=false \ -rtc_build_libjpeg=false \ rtc_build_openmax_dl=false \ rtc_build_libyuv=false \ rtc_include_dav1d_in_internal_decoder_factory=false \ diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/patches/macos/disable_desktop_capture.patch b/webrtc-jni/src/main/cpp/dependencies/webrtc/patches/macos/disable_desktop_capture.patch new file mode 100644 index 0000000..7a29540 --- /dev/null +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/patches/macos/disable_desktop_capture.patch @@ -0,0 +1,8 @@ +--- a/webrtc.gni ++++ b/webrtc.gni +@@ -350,4 +350,2 @@ + # Desktop capturer is supported only on Windows, OSX and Linux. + rtc_desktop_capture_supported = +- (is_win && current_os != "winuwp") || is_mac || +- ((is_linux || is_chromeos) && (rtc_use_x11_extensions || rtc_use_pipewire)) ++ false \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/patches/windows/disable_desktop_capture.patch b/webrtc-jni/src/main/cpp/dependencies/webrtc/patches/windows/disable_desktop_capture.patch new file mode 100644 index 0000000..7a29540 --- /dev/null +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/patches/windows/disable_desktop_capture.patch @@ -0,0 +1,8 @@ +--- a/webrtc.gni ++++ b/webrtc.gni +@@ -350,4 +350,2 @@ + # Desktop capturer is supported only on Windows, OSX and Linux. + rtc_desktop_capture_supported = +- (is_win && current_os != "winuwp") || is_mac || +- ((is_linux || is_chromeos) && (rtc_use_x11_extensions || rtc_use_pipewire)) ++ false \ No newline at end of file From 271b389c1afc1713583db7d13d30976dc6fe1526 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Mon, 8 Dec 2025 01:17:14 -0800 Subject: [PATCH 20/81] Fix desktop capture patch --- webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt | 1 - .../webrtc/patches/macos/disable_desktop_capture.patch | 6 ++++-- .../webrtc/patches/windows/disable_desktop_capture.patch | 6 ++++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt index 5cead18..6c0c4c0 100644 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt @@ -277,7 +277,6 @@ rtc_enable_protobuf=false \ rtc_include_tests=false \ rtc_use_gtk=false \ rtc_build_openmax_dl=false \ -rtc_build_libyuv=false \ rtc_include_dav1d_in_internal_decoder_factory=false \ use_rtti=true \ symbol_level=0 \ diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/patches/macos/disable_desktop_capture.patch b/webrtc-jni/src/main/cpp/dependencies/webrtc/patches/macos/disable_desktop_capture.patch index 7a29540..5c277e4 100644 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/patches/macos/disable_desktop_capture.patch +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/patches/macos/disable_desktop_capture.patch @@ -1,8 +1,10 @@ --- a/webrtc.gni +++ b/webrtc.gni -@@ -350,4 +350,2 @@ +@@ -349,6 +349,5 @@ + # Desktop capturer is supported only on Windows, OSX and Linux. rtc_desktop_capture_supported = - (is_win && current_os != "winuwp") || is_mac || - ((is_linux || is_chromeos) && (rtc_use_x11_extensions || rtc_use_pipewire)) -+ false \ No newline at end of file ++ false + diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/patches/windows/disable_desktop_capture.patch b/webrtc-jni/src/main/cpp/dependencies/webrtc/patches/windows/disable_desktop_capture.patch index 7a29540..5c277e4 100644 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/patches/windows/disable_desktop_capture.patch +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/patches/windows/disable_desktop_capture.patch @@ -1,8 +1,10 @@ --- a/webrtc.gni +++ b/webrtc.gni -@@ -350,4 +350,2 @@ +@@ -349,6 +349,5 @@ + # Desktop capturer is supported only on Windows, OSX and Linux. rtc_desktop_capture_supported = - (is_win && current_os != "winuwp") || is_mac || - ((is_linux || is_chromeos) && (rtc_use_x11_extensions || rtc_use_pipewire)) -+ false \ No newline at end of file ++ false + From 7d8075e7c348a5ce2940ed342a2e29f6e2a76be3 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Mon, 8 Dec 2025 02:11:21 -0800 Subject: [PATCH 21/81] Ignore whitespace in patch application --- webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt index 6c0c4c0..0070bc0 100644 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt @@ -231,7 +231,7 @@ if (PATCHES) message(STATUS "Applying ${PATCH}") execute_process( - COMMAND git apply + COMMAND git apply --ignore-whitespace WORKING_DIRECTORY "${WEBRTC_SRC}" INPUT_FILE "${PATCH}" OUTPUT_VARIABLE OUTPUT @@ -276,7 +276,6 @@ rtc_use_perfetto=false \ rtc_enable_protobuf=false \ rtc_include_tests=false \ rtc_use_gtk=false \ -rtc_build_openmax_dl=false \ rtc_include_dav1d_in_internal_decoder_factory=false \ use_rtti=true \ symbol_level=0 \ From 2bb48f07915738108f6ded8685ccf636d0b6c158 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Mon, 8 Dec 2025 12:21:36 -0800 Subject: [PATCH 22/81] Attempt build optimizations --- webrtc-jni/src/main/cpp/CMakeLists.txt | 2 +- .../cpp/dependencies/webrtc/CMakeLists.txt | 31 +++++++++++++++++-- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/webrtc-jni/src/main/cpp/CMakeLists.txt b/webrtc-jni/src/main/cpp/CMakeLists.txt index 65a9052..cb6cb8a 100644 --- a/webrtc-jni/src/main/cpp/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/CMakeLists.txt @@ -83,7 +83,7 @@ target_link_libraries(${PROJECT_NAME} webrtc) if(APPLE) set_source_files_properties(${SOURCES} PROPERTIES COMPILE_FLAGS "-x objective-c++") target_link_options(${PROJECT_NAME} PRIVATE "-ObjC") - target_link_libraries(${PROJECT_NAME} "-framework Foundation") + target_link_libraries(${PROJECT_NAME} "-framework Foundation" "-framework AVFoundation" "-framework CoreMedia" "-framework CoreVideo") elseif(LINUX) if(NOT TARGET_CPU MATCHES "^arm") set(CXX_LIBS "-static-libgcc -stdlib=libc++ -lc++ -lc++abi") diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt index 0070bc0..2a8f5bb 100644 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt @@ -164,7 +164,7 @@ if(APPLE) ${TARGET_INC_DIR}/sdk/objc/base ) target_compile_definitions(${PROJECT_NAME} PUBLIC WEBRTC_MAC WEBRTC_POSIX) - target_link_libraries(${PROJECT_NAME} "-framework Foundation") + target_link_libraries(${PROJECT_NAME} "-framework Foundation" "-framework AVFoundation" "-framework CoreMedia" "-framework CoreVideo") elseif(LINUX) target_include_directories(${PROJECT_NAME} PUBLIC) target_compile_definitions(${PROJECT_NAME} PUBLIC WEBRTC_LINUX WEBRTC_POSIX) @@ -198,7 +198,7 @@ file(MAKE_DIRECTORY ${WEBRTC_DIR}) message(STATUS "WebRTC: fetch") execute_command( - COMMAND fetch --nohooks webrtc + COMMAND fetch --nohooks --no-history webrtc WORKING_DIRECTORY "${WEBRTC_DIR}" ) @@ -207,11 +207,38 @@ execute_command( COMMAND git checkout . WORKING_DIRECTORY "${WEBRTC_SRC}" ) + +message(STATUS "WebRTC: fetching specific branch ${WEBRTC_BRANCH}") +execute_command( + COMMAND git fetch origin ${WEBRTC_BRANCH}:${WEBRTC_BRANCH} + WORKING_DIRECTORY "${WEBRTC_SRC}" +) + +message(STATUS "WebRTC: checkout to ${WEBRTC_BRANCH}") execute_command( COMMAND git checkout ${WEBRTC_BRANCH} WORKING_DIRECTORY "${WEBRTC_SRC}" ) +message(STATUS "WebRTC: Patching DEPS to skip download of test resources") +set(DEPS_FILE "${WEBRTC_SRC}/DEPS") + +if(EXISTS "${DEPS_FILE}") + file(READ "${DEPS_FILE}" DEPS_CONTENT) + + string(REPLACE + "'src/resources']," + "'src/resources'], 'condition': 'False'," + DEPS_CONTENT + "${DEPS_CONTENT}" + ) + + file(WRITE "${DEPS_FILE}" "${DEPS_CONTENT}") +else() + message(WARNING "WebRTC: DEPS file not found. Optimization skipped.") +endif() + + message(STATUS "WebRTC: sync") execute_command( COMMAND gclient sync From 23618ad064fff61c2b7db21d0c416757209b9d68 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Mon, 8 Dec 2025 12:58:06 -0800 Subject: [PATCH 23/81] Attempt to further optimize gclient sync --- .../cpp/dependencies/webrtc/CMakeLists.txt | 49 ++++++++++++------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt index 2a8f5bb..53833f3 100644 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt @@ -220,29 +220,43 @@ execute_command( WORKING_DIRECTORY "${WEBRTC_SRC}" ) -message(STATUS "WebRTC: Patching DEPS to skip download of test resources") -set(DEPS_FILE "${WEBRTC_SRC}/DEPS") +message(STATUS "WebRTC: optimizing .gclient configuration") -if(EXISTS "${DEPS_FILE}") - file(READ "${DEPS_FILE}" DEPS_CONTENT) - - string(REPLACE - "'src/resources']," - "'src/resources'], 'condition': 'False'," - DEPS_CONTENT - "${DEPS_CONTENT}" - ) - - file(WRITE "${DEPS_FILE}" "${DEPS_CONTENT}") +# Determine target OS for the configuration +if(APPLE) + set(GCLIENT_TARGET_OS "mac") +elseif(WIN32) + set(GCLIENT_TARGET_OS "win") else() - message(WARNING "WebRTC: DEPS file not found. Optimization skipped.") + set(GCLIENT_TARGET_OS "linux") endif() +set(GCLIENT_CONTENT "solutions = [{ + 'name': 'src', + 'url': 'https://webrtc.googlesource.com/src.git', + 'deps_file': 'DEPS', + 'managed': False, + 'custom_deps': { + 'src/resources': None, + }, + 'custom_vars': { + 'checkout_test': False, + 'checkout_tests': False, + 'checkout_android': False, + 'checkout_ios': False, + 'rtc_include_tests': False, + }, +}] +target_os = ['${GCLIENT_TARGET_OS}'] +") + +# Write this optimized config to the .gclient file +file(WRITE "${WEBRTC_DIR}/.gclient" "${GCLIENT_CONTENT}") -message(STATUS "WebRTC: sync") +message(STATUS "WebRTC: Full gclient sync (optimized)") execute_command( - COMMAND gclient sync - WORKING_DIRECTORY "${WEBRTC_DIR}" + COMMAND gclient sync -D -j 16 + WORKING_DIRECTORY "${WEBRTC_SRC}" ) if(LINUX) @@ -292,7 +306,6 @@ rtc_use_pipewire=false \ rtc_link_pipewire=false \ rtc_use_h264=false \ rtc_include_builtin_audio_codecs=false \ -rtc_include_builtin_video_codecs=false \ rtc_enable_win_wgc=false \ rtc_build_libvpx=false \ rtc_build_opus=false \ From a7de53ce75716525a231a584da74e203a180defb Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Mon, 8 Dec 2025 13:35:08 -0800 Subject: [PATCH 24/81] Swutch back to patching deps file --- .../cpp/dependencies/webrtc/CMakeLists.txt | 49 +++++++------------ 1 file changed, 17 insertions(+), 32 deletions(-) diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt index 53833f3..88924cc 100644 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt @@ -220,43 +220,29 @@ execute_command( WORKING_DIRECTORY "${WEBRTC_SRC}" ) -message(STATUS "WebRTC: optimizing .gclient configuration") +message(STATUS "WebRTC: Patching DEPS to skip download of test resources") +set(DEPS_FILE "${WEBRTC_SRC}/DEPS") -# Determine target OS for the configuration -if(APPLE) - set(GCLIENT_TARGET_OS "mac") -elseif(WIN32) - set(GCLIENT_TARGET_OS "win") +if(EXISTS "${DEPS_FILE}") + file(READ "${DEPS_FILE}" DEPS_CONTENT) + + string(REPLACE + "'src/resources']," + "'src/resources'], 'condition': 'False'," + DEPS_CONTENT + "${DEPS_CONTENT}" + ) + + file(WRITE "${DEPS_FILE}" "${DEPS_CONTENT}") else() - set(GCLIENT_TARGET_OS "linux") + message(WARNING "WebRTC: DEPS file not found. Optimization skipped.") endif() -set(GCLIENT_CONTENT "solutions = [{ - 'name': 'src', - 'url': 'https://webrtc.googlesource.com/src.git', - 'deps_file': 'DEPS', - 'managed': False, - 'custom_deps': { - 'src/resources': None, - }, - 'custom_vars': { - 'checkout_test': False, - 'checkout_tests': False, - 'checkout_android': False, - 'checkout_ios': False, - 'rtc_include_tests': False, - }, -}] -target_os = ['${GCLIENT_TARGET_OS}'] -") - -# Write this optimized config to the .gclient file -file(WRITE "${WEBRTC_DIR}/.gclient" "${GCLIENT_CONTENT}") -message(STATUS "WebRTC: Full gclient sync (optimized)") +message(STATUS "WebRTC: sync") execute_command( - COMMAND gclient sync -D -j 16 - WORKING_DIRECTORY "${WEBRTC_SRC}" + COMMAND gclient sync -j8 + WORKING_DIRECTORY "${WEBRTC_DIR}" ) if(LINUX) @@ -293,7 +279,6 @@ is_clang=true \ is_debug=false \ is_component_build=false \ treat_warnings_as_errors=false \ -rtc_include_ilbc=false \ rtc_include_opus=false \ rtc_opus_support_120ms_ptime=false \ rtc_opus_variable_complexity=false \ From fc49076073419c35f84b95afa900d034f0eadb16 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Mon, 8 Dec 2025 13:43:10 -0800 Subject: [PATCH 25/81] Use no history on final gclient sync --- webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt index 88924cc..2c74ba9 100644 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt @@ -241,7 +241,7 @@ endif() message(STATUS "WebRTC: sync") execute_command( - COMMAND gclient sync -j8 + COMMAND gclient sync --no-history -j8 WORKING_DIRECTORY "${WEBRTC_DIR}" ) From dea8fd0c8bcb083bd9335b01c2661a58383cdc66 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Mon, 8 Dec 2025 14:44:24 -0800 Subject: [PATCH 26/81] Fix windows compile --- webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt index 2c74ba9..1b090fd 100644 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt @@ -170,7 +170,7 @@ elseif(LINUX) target_compile_definitions(${PROJECT_NAME} PUBLIC WEBRTC_LINUX WEBRTC_POSIX) elseif(WIN32) target_compile_definitions(${PROJECT_NAME} PUBLIC WEBRTC_WIN NOMINMAX WIN32_LEAN_AND_MEAN NDEBUG) - target_link_libraries(${PROJECT_NAME} user32 iphlpapi secur32 ws2_32) + target_link_libraries(${PROJECT_NAME} user32 iphlpapi secur32 ws2_32 winmm) endif() if(EXISTS "${WEBRTC_LIB_PATH}" OR EXISTS "${WEBRTC_LIB_PATH_INSTALLED}") @@ -241,7 +241,7 @@ endif() message(STATUS "WebRTC: sync") execute_command( - COMMAND gclient sync --no-history -j8 + COMMAND gclient sync -D --no-history -j8 WORKING_DIRECTORY "${WEBRTC_DIR}" ) @@ -300,7 +300,6 @@ rtc_include_internal_audio_device=false \ rtc_use_perfetto=false \ rtc_enable_protobuf=false \ rtc_include_tests=false \ -rtc_use_gtk=false \ rtc_include_dav1d_in_internal_decoder_factory=false \ use_rtti=true \ symbol_level=0 \ From 9c568ca1f5af922704028b77bebe3c13f645e2eb Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Mon, 8 Dec 2025 19:18:19 -0800 Subject: [PATCH 27/81] Further compiler optimizations --- .../main/cpp/dependencies/webrtc/CMakeLists.txt | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt index 1b090fd..07454c0 100644 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt @@ -301,13 +301,25 @@ rtc_use_perfetto=false \ rtc_enable_protobuf=false \ rtc_include_tests=false \ rtc_include_dav1d_in_internal_decoder_factory=false \ +rtc_enable_google_benchmarks=false \ +rtc_video_psnr=false \ use_rtti=true \ symbol_level=0 \ use_dbus=false \ use_udev=false \ -rtc_use_pulseaudio=false \ rtc_disable_metrics=true \ -proprietary_codecs=false") +proprietary_codecs=false \ +is_official_build=true \ +enable_stripping=true \ +enable_libaom=false \ +enable_freetype=false \ +libyuv_disable_jpeg=true \ +archive_seed_corpus=false \ +use_aura=false \ +use_blink=false \ +use_libjpeg_turbo=false \ +use_ozone=false \ +libyuv_include_tests=false") if(APPLE) set(COMPILE_ARGS "${COMPILE_ARGS} mac_deployment_target=\"${CMAKE_OSX_DEPLOYMENT_TARGET}\"") From 93072f685070896958126e96d12386a2abe3373e Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Mon, 8 Dec 2025 19:49:49 -0800 Subject: [PATCH 28/81] Fix pipeline --- webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt index 07454c0..0a2b3ed 100644 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt @@ -309,7 +309,7 @@ use_dbus=false \ use_udev=false \ rtc_disable_metrics=true \ proprietary_codecs=false \ -is_official_build=true \ +is_official_build=false \ enable_stripping=true \ enable_libaom=false \ enable_freetype=false \ From 1e51266d7b5a864182e978524ed79ea958c17c0d Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Mon, 8 Dec 2025 20:19:20 -0800 Subject: [PATCH 29/81] Don't strip symbols --- webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt index 0a2b3ed..ae29959 100644 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt @@ -309,8 +309,6 @@ use_dbus=false \ use_udev=false \ rtc_disable_metrics=true \ proprietary_codecs=false \ -is_official_build=false \ -enable_stripping=true \ enable_libaom=false \ enable_freetype=false \ libyuv_disable_jpeg=true \ From 93f22b499b9e6d1a36c1f263b355b38aa9b3ba95 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Mon, 8 Dec 2025 20:22:55 -0800 Subject: [PATCH 30/81] Don't disable metrics --- webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt index ae29959..1709b7f 100644 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt @@ -307,7 +307,6 @@ use_rtti=true \ symbol_level=0 \ use_dbus=false \ use_udev=false \ -rtc_disable_metrics=true \ proprietary_codecs=false \ enable_libaom=false \ enable_freetype=false \ From f890c874f038d651d17c006b4584cd66e0c81501 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Mon, 8 Dec 2025 20:57:13 -0800 Subject: [PATCH 31/81] Try to fix build --- .../src/main/cpp/dependencies/webrtc/CMakeLists.txt | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt index 1709b7f..61e67ee 100644 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt @@ -307,16 +307,7 @@ use_rtti=true \ symbol_level=0 \ use_dbus=false \ use_udev=false \ -proprietary_codecs=false \ -enable_libaom=false \ -enable_freetype=false \ -libyuv_disable_jpeg=true \ -archive_seed_corpus=false \ -use_aura=false \ -use_blink=false \ -use_libjpeg_turbo=false \ -use_ozone=false \ -libyuv_include_tests=false") +proprietary_codecs=false") if(APPLE) set(COMPILE_ARGS "${COMPILE_ARGS} mac_deployment_target=\"${CMAKE_OSX_DEPLOYMENT_TARGET}\"") From 57e3fc1390df84cf676e94e3142bf35093c9a919 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Mon, 8 Dec 2025 21:46:04 -0800 Subject: [PATCH 32/81] Test with is_official_build opts --- webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt index 61e67ee..6777425 100644 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt @@ -307,7 +307,8 @@ use_rtti=true \ symbol_level=0 \ use_dbus=false \ use_udev=false \ -proprietary_codecs=false") +proprietary_codecs=false \ +is_official_build=true") if(APPLE) set(COMPILE_ARGS "${COMPILE_ARGS} mac_deployment_target=\"${CMAKE_OSX_DEPLOYMENT_TARGET}\"") From 31b9a70a8f9858e4b36e63ad5e5c27b6121efe8d Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Mon, 8 Dec 2025 22:13:32 -0800 Subject: [PATCH 33/81] More compiler opts --- webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt index 6777425..ffea4f9 100644 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt @@ -308,7 +308,11 @@ symbol_level=0 \ use_dbus=false \ use_udev=false \ proprietary_codecs=false \ -is_official_build=true") +enable_libaom=false \ +enable_freetype=false \ +libyuv_disable_jpeg=true \ +libyuv_disable_rvv=true \ +libyuv_include_tests=false") if(APPLE) set(COMPILE_ARGS "${COMPILE_ARGS} mac_deployment_target=\"${CMAKE_OSX_DEPLOYMENT_TARGET}\"") From c2d123a0d24b978b0e3827f48e8fb9f3a449a529 Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Mon, 15 Dec 2025 10:54:18 -0800 Subject: [PATCH 34/81] Make local compile more straightforward Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/build-macos-x86_64/action.yml | 2 +- .github/actions/build/action.yml | 2 +- .github/actions/prepare-linux/action.yml | 2 +- .../actions/release-macos-x86_64/action.yml | 2 +- .github/actions/release/action.yml | 2 +- .github/workflows/build.yml | 3 +- .github/workflows/release.yml | 3 +- .gitignore | 7 ++ .vscode/extensions.json | 13 ++++ .vscode/settings.json | 3 + webrtc-jni/pom.xml | 11 +--- webrtc-jni/src/main/cpp/CMakeLists.txt | 34 ++++++++++ .../cpp/dependencies/webrtc/CMakeLists.txt | 11 ++-- .../cpp/toolchain/aarch32-linux-clang.cmake | 65 ++++++++++++++----- .../cpp/toolchain/aarch64-linux-clang.cmake | 65 ++++++++++++++----- .../cpp/toolchain/x86_64-linux-clang.cmake | 62 +++++++++++++----- 16 files changed, 217 insertions(+), 70 deletions(-) create mode 100644 .vscode/extensions.json create mode 100644 .vscode/settings.json diff --git a/.github/actions/build-macos-x86_64/action.yml b/.github/actions/build-macos-x86_64/action.yml index 92c8733..924ff25 100644 --- a/.github/actions/build-macos-x86_64/action.yml +++ b/.github/actions/build-macos-x86_64/action.yml @@ -26,7 +26,7 @@ runs: - name: Set up WebRTC cache uses: actions/cache@v4 with: - path: ~/${{ env.WEBRTC_INSTALL_FOLDER }} + path: ${{ env.WEBRTC_CHECKOUT_FOLDER }}/build key: webrtc-${{ env.WEBRTC_CACHE_BRANCH }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/pom.xml') }} restore-keys: webrtc-${{ env.WEBRTC_CACHE_BRANCH }}-${{ inputs.platform-name }}- diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index c68ac2d..47557d8 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -26,7 +26,7 @@ runs: - name: Set up WebRTC cache uses: actions/cache@v4 with: - path: ~/${{ env.WEBRTC_INSTALL_FOLDER }} + path: ${{ env.WEBRTC_CHECKOUT_FOLDER }}/build key: webrtc-${{ env.WEBRTC_CACHE_BRANCH }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/pom.xml') }} restore-keys: webrtc-${{ env.WEBRTC_CACHE_BRANCH }}-${{ inputs.platform-name }}- diff --git a/.github/actions/prepare-linux/action.yml b/.github/actions/prepare-linux/action.yml index 6fbf9f3..cde04ac 100644 --- a/.github/actions/prepare-linux/action.yml +++ b/.github/actions/prepare-linux/action.yml @@ -31,7 +31,7 @@ runs: - name: Install required packages run: | sudo apt update - sudo apt install -y binutils cmake git locales lsb-release ninja-build pipewire pipewire-pulse pkg-config python3 python3-setuptools rsync unzip wget xz-utils + sudo apt install -y binutils cmake git locales lsb-release ninja-build pkg-config python3 python3-setuptools rsync unzip wget xz-utils # Chromium Clang to be used with the clang toolchain file #curl -s https://raw.githubusercontent.com/chromium/chromium/main/tools/clang/scripts/update.py | python3 - --output-dir=/opt/clang diff --git a/.github/actions/release-macos-x86_64/action.yml b/.github/actions/release-macos-x86_64/action.yml index f9f8650..1180eec 100644 --- a/.github/actions/release-macos-x86_64/action.yml +++ b/.github/actions/release-macos-x86_64/action.yml @@ -34,7 +34,7 @@ runs: - name: Set up WebRTC cache uses: actions/cache@v4 with: - path: ~/${{ env.WEBRTC_INSTALL_FOLDER }} + path: ${{ env.WEBRTC_CHECKOUT_FOLDER }}/build key: webrtc-${{ env.WEBRTC_CACHE_BRANCH }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/pom.xml') }} restore-keys: webrtc-${{ env.WEBRTC_CACHE_BRANCH }}-${{ inputs.platform-name }}- diff --git a/.github/actions/release/action.yml b/.github/actions/release/action.yml index 357decc..f7a950f 100644 --- a/.github/actions/release/action.yml +++ b/.github/actions/release/action.yml @@ -34,7 +34,7 @@ runs: - name: Set up WebRTC cache uses: actions/cache@v4 with: - path: ~/${{ env.WEBRTC_INSTALL_FOLDER }} + path: ${{ env.WEBRTC_CHECKOUT_FOLDER }}/build key: webrtc-${{ env.WEBRTC_CACHE_BRANCH }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/pom.xml') }} restore-keys: webrtc-${{ env.WEBRTC_CACHE_BRANCH }}-${{ inputs.platform-name }}- diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c22bf28..ff80b97 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,8 +18,7 @@ on: env: WEBRTC_CACHE_BRANCH: 7339 - WEBRTC_CHECKOUT_FOLDER: webrtc - WEBRTC_INSTALL_FOLDER: webrtc/build + WEBRTC_CHECKOUT_FOLDER: ~/webrtc jobs: build-windows: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fc11c18..2ea33fe 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,8 +10,7 @@ on: env: WEBRTC_CACHE_BRANCH: 7339 - WEBRTC_CHECKOUT_FOLDER: webrtc - WEBRTC_INSTALL_FOLDER: webrtc/build + WEBRTC_CHECKOUT_FOLDER: ~/webrtc jobs: changelog: diff --git a/.gitignore b/.gitignore index 624afc1..baaf034 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,10 @@ *.so *.dylib *.dll + +webrtc-jni/src/main/cpp/dependencies/webrtc/linux/debian*amd64* +webrtc-jni/src/main/cpp/dependencies/webrtc/linux/debian*armhf* +webrtc-jni/src/main/cpp/dependencies/webrtc/linux/debian*arm64* +webrtc-jni/src/main/cpp/dependencies/webrtc/webrtc-source/ +.cache/ +compile_commands.json \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..ff33d5b --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + "recommendations": [ + "ms-vscode.cpptools", + "llvm-vs-code-extensions.vscode-clangd", + "ms-vscode.cmake-tools", + "vscjava.vscode-java-debug", + "vscjava.vscode-gradle", + "redhat.java", + "vscjava.vscode-maven", + "vscjava.vscode-java-dependency", + "vscjava.vscode-java-test" + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..6d6682a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "C_Cpp.intelliSenseEngine": "disabled" +} \ No newline at end of file diff --git a/webrtc-jni/pom.xml b/webrtc-jni/pom.xml index 8d7f9af..99fe25e 100644 --- a/webrtc-jni/pom.xml +++ b/webrtc-jni/pom.xml @@ -13,8 +13,6 @@ branch-heads/7339 - ${user.home}/webrtc - ${user.home}/webrtc/build Release @@ -99,12 +97,6 @@ - - @@ -114,6 +106,9 @@ + diff --git a/webrtc-jni/src/main/cpp/CMakeLists.txt b/webrtc-jni/src/main/cpp/CMakeLists.txt index cb6cb8a..8c63942 100644 --- a/webrtc-jni/src/main/cpp/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/CMakeLists.txt @@ -7,6 +7,15 @@ endif() project(webrtc-java) +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND LINUX) + add_compile_options(-nostdinc++ -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE) + add_link_options(-stdlib=libc++ -v -Wl,--verbose) + find_program(LLD_PATH ld.lld) + if(LLD_PATH) + add_link_options(-fuse-ld=lld) + endif() +endif() + if(UNIX AND NOT APPLE) # Apply the sysroot configuration for the actual build if(DEFERRED_SYSROOT) @@ -100,3 +109,28 @@ install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX} COMPONENT Runtime LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX} COMPONENT Runtime ) + +if (PROJECT_IS_TOP_LEVEL) + get_filename_component(TARGET_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../.." ABSOLUTE) + + set(COMPILE_COMMANDS_SRC "${CMAKE_BINARY_DIR}/compile_commands.json") + set(COMPILE_COMMANDS_DST "${TARGET_DIR}/compile_commands.json") + + if (WIN32) + # Windows: Copy instead of symlink to avoid permission issues + execute_process( + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${COMPILE_COMMANDS_SRC}" + "${COMPILE_COMMANDS_DST}" + ) + message(STATUS "Copied compile_commands.json to: ${TARGET_DIR}") + else() + # Unix: Symlink + execute_process( + COMMAND ${CMAKE_COMMAND} -E create_symlink + "${COMPILE_COMMANDS_SRC}" + "${COMPILE_COMMANDS_DST}" + ) + message(STATUS "Created compile_commands.json symlink in: ${TARGET_DIR}") + endif() +endif() \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt index ffea4f9..23e5b25 100644 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt @@ -36,15 +36,12 @@ if(NOT DEFINED WEBRTC_BRANCH) endif() if(NOT DEFINED WEBRTC_SRC_DIR) - if(DEFINED ENV{CTEST_REAL_HOME}) - set(WEBRTC_SRC_DIR "$ENV{CTEST_REAL_HOME}") + if (DEFINED ENV{WEBRTC_CHECKOUT_FOLDER}) + set(WEBRTC_SRC_DIR "$ENV{WEBRTC_CHECKOUT_FOLDER}") else() - set(WEBRTC_SRC_DIR "$ENV{HOME}") - endif() - - if(NOT WEBRTC_SRC_DIR AND WIN32) - file(TO_CMAKE_PATH "$ENV{USERPROFILE}" WEBRTC_SRC_DIR) + set(WEBRTC_SRC_DIR "${CMAKE_CURRENT_LIST_DIR}/webrtc-source") endif() + file(MAKE_DIRECTORY "${WEBRTC_SRC_DIR}") endif() if(NOT DEFINED WEBRTC_INSTALL_DIR) diff --git a/webrtc-jni/src/main/cpp/toolchain/aarch32-linux-clang.cmake b/webrtc-jni/src/main/cpp/toolchain/aarch32-linux-clang.cmake index b962ad6..185c7f7 100644 --- a/webrtc-jni/src/main/cpp/toolchain/aarch32-linux-clang.cmake +++ b/webrtc-jni/src/main/cpp/toolchain/aarch32-linux-clang.cmake @@ -1,27 +1,62 @@ set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR arm) -set(CMAKE_C_COMPILER /opt/clang/bin/clang) -set(CMAKE_CXX_COMPILER /opt/clang/bin/clang++) -set(CMAKE_AR /opt/clang/bin/llvm-ar) + +find_program(CLANG_BIN clang + HINTS /opt/clang/bin /usr/bin /usr/local/bin + DOC "Path to clang executable" +) +find_program(CLANGXX_BIN clang++ + HINTS /opt/clang/bin /usr/bin /usr/local/bin + DOC "Path to clang++ executable" +) + +if(NOT CLANG_BIN OR NOT CLANGXX_BIN) + message(FATAL_ERROR "Clang not found. Please install clang.") +endif() + +set(CMAKE_C_COMPILER ${CLANG_BIN}) +set(CMAKE_CXX_COMPILER ${CLANGXX_BIN}) + +find_program(LLVM_AR_BIN llvm-ar + HINTS /opt/clang/bin /usr/bin /usr/local/bin +) +if(LLVM_AR_BIN) + set(CMAKE_AR ${LLVM_AR_BIN}) + find_program(LLVM_RANLIB_BIN llvm-ranlib HINTS /opt/clang/bin /usr/bin /usr/local/bin) + if(LLVM_RANLIB_BIN) + set(CMAKE_RANLIB ${LLVM_RANLIB_BIN}) + endif() +endif() + +find_program(LLD_BIN ld.lld + HINTS /opt/clang/bin /usr/bin /usr/local/bin +) set(TARGET_TRIPLE arm-linux-gnueabihf) set(CMAKE_C_FLAGS "--target=${TARGET_TRIPLE} -march=armv7-a -mfloat-abi=hard -mfpu=neon") +if(LLD_BIN) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fuse-ld=lld") +endif() + set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -v -Wl,--verbose") -foreach(LINKER SHARED_LINKER) - set(CMAKE_${LINKER}_FLAGS "-fuse-ld=lld -Wl,-s -v -Wl,--verbose") -endforeach() +get_filename_component(TOOLCHAIN_DIR ${CMAKE_CURRENT_LIST_FILE} DIRECTORY) +set(LOCAL_SYSROOT_PATH "${TOOLCHAIN_DIR}/../dependencies/webrtc/linux") -# IMPORTANT: Find sysroot but DO NOT set CMAKE_SYSROOT yet -file(GLOB LINUX_SYSROOT "/opt/sysroot/debian*armhf*") -if(NOT LINUX_SYSROOT) - message(FATAL_ERROR "No debian armhf sysroot found in /opt/sysroot/") -endif() +file(GLOB LINUX_SYSROOT + "/opt/sysroot/debian*armhf*" + "${LOCAL_SYSROOT_PATH}/debian*armhf*" +) -# Store sysroot path for later application -# This will be set after project() call in the main CMakeLists.txt -set(DEFERRED_SYSROOT ${LINUX_SYSROOT}) +if(LINUX_SYSROOT) + list(GET LINUX_SYSROOT 0 SELECTED_SYSROOT) + message(STATUS "Found Sysroot: ${SELECTED_SYSROOT}") + set(CMAKE_SYSROOT ${SELECTED_SYSROOT}) + set(DEFERRED_SYSROOT ${SELECTED_SYSROOT}) +else() + message(FATAL_ERROR "No armhf sysroot found. Please run 'python3 install-sysroot.py --arch=armhf'") +endif() -set(TARGET_CPU "arm") \ No newline at end of file +set(TARGET_CPU "arm") \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/toolchain/aarch64-linux-clang.cmake b/webrtc-jni/src/main/cpp/toolchain/aarch64-linux-clang.cmake index e151e00..5d4d843 100644 --- a/webrtc-jni/src/main/cpp/toolchain/aarch64-linux-clang.cmake +++ b/webrtc-jni/src/main/cpp/toolchain/aarch64-linux-clang.cmake @@ -1,27 +1,62 @@ set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR aarch64) -set(CMAKE_C_COMPILER /opt/clang/bin/clang) -set(CMAKE_CXX_COMPILER /opt/clang/bin/clang++) -set(CMAKE_AR /opt/clang/bin/llvm-ar) + +find_program(CLANG_BIN clang + HINTS /opt/clang/bin /usr/bin /usr/local/bin + DOC "Path to clang executable" +) +find_program(CLANGXX_BIN clang++ + HINTS /opt/clang/bin /usr/bin /usr/local/bin + DOC "Path to clang++ executable" +) + +if(NOT CLANG_BIN OR NOT CLANGXX_BIN) + message(FATAL_ERROR "Clang not found. Please install clang.") +endif() + +set(CMAKE_C_COMPILER ${CLANG_BIN}) +set(CMAKE_CXX_COMPILER ${CLANGXX_BIN}) + +find_program(LLVM_AR_BIN llvm-ar + HINTS /opt/clang/bin /usr/bin /usr/local/bin +) +if(LLVM_AR_BIN) + set(CMAKE_AR ${LLVM_AR_BIN}) + find_program(LLVM_RANLIB_BIN llvm-ranlib HINTS /opt/clang/bin /usr/bin /usr/local/bin) + if(LLVM_RANLIB_BIN) + set(CMAKE_RANLIB ${LLVM_RANLIB_BIN}) + endif() +endif() + +find_program(LLD_BIN ld.lld + HINTS /opt/clang/bin /usr/bin /usr/local/bin +) set(TARGET_TRIPLE aarch64-linux-gnu) set(CMAKE_C_FLAGS "--target=${TARGET_TRIPLE}") +if(LLD_BIN) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fuse-ld=lld") +endif() + set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -v -Wl,--verbose") -foreach(LINKER SHARED_LINKER) - set(CMAKE_${LINKER}_FLAGS "-fuse-ld=lld -Wl,-s -v -Wl,--verbose") -endforeach() +get_filename_component(TOOLCHAIN_DIR ${CMAKE_CURRENT_LIST_FILE} DIRECTORY) +set(LOCAL_SYSROOT_PATH "${TOOLCHAIN_DIR}/../dependencies/webrtc/linux") -# IMPORTANT: Find sysroot but DO NOT set CMAKE_SYSROOT yet -file(GLOB LINUX_SYSROOT "/opt/sysroot/debian*arm64*") -if(NOT LINUX_SYSROOT) - message(FATAL_ERROR "No debian arm64 sysroot found in /opt/sysroot/") -endif() +file(GLOB LINUX_SYSROOT + "/opt/sysroot/debian*arm64*" + "${LOCAL_SYSROOT_PATH}/debian*arm64*" +) -# Store sysroot path for later application -# This will be set after project() call in the main CMakeLists.txt -set(DEFERRED_SYSROOT ${LINUX_SYSROOT}) +if(LINUX_SYSROOT) + list(GET LINUX_SYSROOT 0 SELECTED_SYSROOT) + message(STATUS "Found Sysroot: ${SELECTED_SYSROOT}") + set(CMAKE_SYSROOT ${SELECTED_SYSROOT}) + set(DEFERRED_SYSROOT ${SELECTED_SYSROOT}) +else() + message(FATAL_ERROR "No arm64 sysroot found. Please run 'python3 install-sysroot.py --arch=arm64'") +endif() -set(TARGET_CPU "arm64") \ No newline at end of file +set(TARGET_CPU "arm64") \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/toolchain/x86_64-linux-clang.cmake b/webrtc-jni/src/main/cpp/toolchain/x86_64-linux-clang.cmake index da387d0..69db531 100644 --- a/webrtc-jni/src/main/cpp/toolchain/x86_64-linux-clang.cmake +++ b/webrtc-jni/src/main/cpp/toolchain/x86_64-linux-clang.cmake @@ -1,24 +1,54 @@ set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR x86_64) -set(CMAKE_C_COMPILER /opt/clang/bin/clang) -set(CMAKE_CXX_COMPILER /opt/clang/bin/clang++) -set(CMAKE_AR /opt/clang/bin/llvm-ar) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdinc++ -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE") -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -v -Wl,--verbose") +find_program(CLANG_BIN clang + HINTS /opt/clang/bin /usr/bin /usr/local/bin + DOC "Path to clang executable" +) +find_program(CLANGXX_BIN clang++ + HINTS /opt/clang/bin /usr/bin /usr/local/bin + DOC "Path to clang++ executable" +) -foreach(LINKER SHARED_LINKER) - set(CMAKE_${LINKER}_FLAGS "-fuse-ld=lld -Wl,-s -v -Wl,--verbose") -endforeach() +if(NOT CLANG_BIN OR NOT CLANGXX_BIN) + message(FATAL_ERROR "Clang not found. Please install clang.") +endif() + +set(CMAKE_C_COMPILER ${CLANG_BIN}) +set(CMAKE_CXX_COMPILER ${CLANGXX_BIN}) + +find_program(LLVM_AR_BIN llvm-ar + HINTS /opt/clang/bin /usr/bin /usr/local/bin + DOC "Path to llvm-ar executable" +) + +if(LLVM_AR_BIN) + set(CMAKE_AR ${LLVM_AR_BIN}) + find_program(LLVM_RANLIB_BIN llvm-ranlib + HINTS /opt/clang/bin /usr/bin /usr/local/bin + ) + if(LLVM_RANLIB_BIN) + set(CMAKE_RANLIB ${LLVM_RANLIB_BIN}) + endif() +else() + message(WARNING "llvm-ar not found. Using system default ar.") +endif() + +get_filename_component(TOOLCHAIN_DIR ${CMAKE_CURRENT_LIST_FILE} DIRECTORY) +set(LOCAL_SYSROOT_PATH "${TOOLCHAIN_DIR}/../dependencies/webrtc/linux") + +file(GLOB LINUX_SYSROOT + "/opt/sysroot/debian*amd64*" + "${LOCAL_SYSROOT_PATH}/debian*amd64*" +) -# IMPORTANT: Find sysroot but DO NOT set CMAKE_SYSROOT yet -file(GLOB LINUX_SYSROOT "/opt/sysroot/debian*amd64*") -if(NOT LINUX_SYSROOT) - message(FATAL_ERROR "No debian amd64 sysroot found in /opt/sysroot/") +if(LINUX_SYSROOT) + list(GET LINUX_SYSROOT 0 SELECTED_SYSROOT) + message(STATUS "Found Sysroot: ${SELECTED_SYSROOT}") + set(DEFERRED_SYSROOT ${SELECTED_SYSROOT}) +else() + message(WARNING "No sysroot found. Build may depend on system libraries.") endif() -# Store sysroot path for later application -# This will be set after project() call in the main CMakeLists.txt -set(DEFERRED_SYSROOT ${LINUX_SYSROOT}) +set(TARGET_CPU "x64") -set(TARGET_CPU "x64") From a8c6e7212e05d573a5bc8d8fa661f395d7cbfaa0 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Mon, 15 Dec 2025 17:06:22 -0800 Subject: [PATCH 35/81] Fix compile --- webrtc-jni/src/main/cpp/CMakeLists.txt | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/webrtc-jni/src/main/cpp/CMakeLists.txt b/webrtc-jni/src/main/cpp/CMakeLists.txt index 8c63942..b730fe1 100644 --- a/webrtc-jni/src/main/cpp/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/CMakeLists.txt @@ -8,11 +8,19 @@ endif() project(webrtc-java) if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND LINUX) - add_compile_options(-nostdinc++ -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE) - add_link_options(-stdlib=libc++ -v -Wl,--verbose) - find_program(LLD_PATH ld.lld) + find_program(LLD_PATH ld.lld + HINTS /opt/clang/bin /usr/bin /usr/local/bin + DOC "Path to lld linker" + ) if(LLD_PATH) + message(STATUS "Found LLD: ${LLD_PATH}") add_link_options(-fuse-ld=lld) + else() + message(WARNING "LLD not found! Linker errors may occur.") + endif() + if(TARGET_CPU STREQUAL "x64") + add_compile_options(-nostdinc++ -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE) + add_link_options(-stdlib=libc++ -v -Wl,--verbose) endif() endif() From e14c29714a20d6bb6992255e86038055281c4b59 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Tue, 16 Dec 2025 20:16:36 -0800 Subject: [PATCH 36/81] Initial gradle setup --- .gitignore | 13 +- build.gradle.kts | 23 + docs/.gitignore | 4 - docs/.vitepress/config.mts | 49 - docs/.vitepress/footer.ts | 6 - docs/.vitepress/head.ts | 27 - docs/.vitepress/nav.ts | 30 - docs/.vitepress/sidebar.ts | 102 - docs/.vitepress/theme/index.ts | 17 - docs/.vitepress/theme/style.css | 139 - docs/.vitepress/versions.ts | 4 - docs/guide/audio/audio-devices.md | 140 - docs/guide/audio/audio-processing.md | 340 --- docs/guide/audio/custom-audio-source.md | 190 -- docs/guide/audio/dtmf-sender.md | 164 -- docs/guide/audio/headless-audio.md | 107 - docs/guide/build.md | 31 - docs/guide/data/data-channels.md | 304 --- docs/guide/examples.md | 97 - docs/guide/get-started.md | 306 --- docs/guide/index.md | 40 - docs/guide/introduction.md | 24 - docs/guide/media/constraints.md | 127 - docs/guide/media/directionality.md | 143 -- docs/guide/media/media-devices.md | 182 -- docs/guide/monitoring/logging.md | 135 - docs/guide/monitoring/rtc-stats.md | 395 --- .../guide/networking/port-allocator-config.md | 105 - docs/guide/video/camera-capture.md | 299 --- docs/guide/video/custom-video-source.md | 192 -- docs/guide/video/desktop-capture.md | 170 -- docs/index.md | 36 - docs/package-lock.json | 2261 ----------------- docs/package.json | 12 - docs/public/apple-touch-icon.png | Bin 10117 -> 0 bytes docs/public/favicon-96x96.png | Bin 5478 -> 0 bytes docs/public/favicon.ico | Bin 15086 -> 0 bytes docs/public/favicon.svg | 3 - docs/public/logo.png | Bin 36847 -> 0 bytes docs/public/site.webmanifest | 21 - docs/public/web-app-manifest-192x192.png | Bin 8989 -> 0 bytes docs/public/web-app-manifest-512x512.png | Bin 23100 -> 0 bytes docs/tools/audio/audio-converter.md | 107 - docs/tools/audio/audio-player.md | 97 - docs/tools/audio/audio-recorder.md | 65 - docs/tools/audio/voice-activity-detector.md | 104 - docs/tools/desktop/power-management.md | 61 - docs/tools/desktop/screen-capturer.md | 112 - docs/tools/desktop/window-capturer.md | 105 - docs/tools/index.md | 41 - docs/tools/video/video-buffer-converter.md | 145 -- docs/tools/video/video-capturer.md | 110 - docs/tsconfig.json | 12 - gradle/libs.versions.toml | 15 + pom.xml | 377 --- settings.gradle.kts | 11 + webrtc-examples/pom.xml | 97 - .../examples/web/client/SignalingManager.java | 415 --- .../examples/web/client/WebSocketClient.java | 453 ---- .../web/connection/PeerConnectionManager.java | 336 --- .../PeerConnectionSignalingHandler.java | 51 - .../web/model/IceCandidateMessage.java | 170 -- .../examples/web/model/JoinMessage.java | 207 -- .../examples/web/model/LeaveMessage.java | 34 - .../examples/web/model/MessageType.java | 87 - .../web/model/SessionDescriptionMessage.java | 136 - .../examples/web/model/SignalingMessage.java | 117 - .../src/main/java/module-info.java | 13 - .../src/main/resources/keystore.p12 | Bin 2723 -> 0 bytes .../src/main/resources/logging.properties | 11 - .../resources/web/PeerConnectionManager.js | 212 -- .../main/resources/web/SignalingChannel.js | 142 -- .../src/main/resources/web/WebRTCClient.js | 332 --- .../src/main/resources/web/index.html | 158 -- .../src/main/resources/web/main.js | 6 - webrtc-jni/build.gradle.kts | 127 + webrtc-jni/pom.xml | 215 -- webrtc/build.gradle.kts | 78 + webrtc/pom.xml | 56 - 79 files changed, 266 insertions(+), 10787 deletions(-) create mode 100644 build.gradle.kts delete mode 100644 docs/.gitignore delete mode 100644 docs/.vitepress/config.mts delete mode 100644 docs/.vitepress/footer.ts delete mode 100644 docs/.vitepress/head.ts delete mode 100644 docs/.vitepress/nav.ts delete mode 100644 docs/.vitepress/sidebar.ts delete mode 100644 docs/.vitepress/theme/index.ts delete mode 100644 docs/.vitepress/theme/style.css delete mode 100644 docs/.vitepress/versions.ts delete mode 100644 docs/guide/audio/audio-devices.md delete mode 100644 docs/guide/audio/audio-processing.md delete mode 100644 docs/guide/audio/custom-audio-source.md delete mode 100644 docs/guide/audio/dtmf-sender.md delete mode 100644 docs/guide/audio/headless-audio.md delete mode 100644 docs/guide/build.md delete mode 100644 docs/guide/data/data-channels.md delete mode 100644 docs/guide/examples.md delete mode 100644 docs/guide/get-started.md delete mode 100644 docs/guide/index.md delete mode 100644 docs/guide/introduction.md delete mode 100644 docs/guide/media/constraints.md delete mode 100644 docs/guide/media/directionality.md delete mode 100644 docs/guide/media/media-devices.md delete mode 100644 docs/guide/monitoring/logging.md delete mode 100644 docs/guide/monitoring/rtc-stats.md delete mode 100644 docs/guide/networking/port-allocator-config.md delete mode 100644 docs/guide/video/camera-capture.md delete mode 100644 docs/guide/video/custom-video-source.md delete mode 100644 docs/guide/video/desktop-capture.md delete mode 100644 docs/index.md delete mode 100644 docs/package-lock.json delete mode 100644 docs/package.json delete mode 100644 docs/public/apple-touch-icon.png delete mode 100644 docs/public/favicon-96x96.png delete mode 100644 docs/public/favicon.ico delete mode 100644 docs/public/favicon.svg delete mode 100644 docs/public/logo.png delete mode 100644 docs/public/site.webmanifest delete mode 100644 docs/public/web-app-manifest-192x192.png delete mode 100644 docs/public/web-app-manifest-512x512.png delete mode 100644 docs/tools/audio/audio-converter.md delete mode 100644 docs/tools/audio/audio-player.md delete mode 100644 docs/tools/audio/audio-recorder.md delete mode 100644 docs/tools/audio/voice-activity-detector.md delete mode 100644 docs/tools/desktop/power-management.md delete mode 100644 docs/tools/desktop/screen-capturer.md delete mode 100644 docs/tools/desktop/window-capturer.md delete mode 100644 docs/tools/index.md delete mode 100644 docs/tools/video/video-buffer-converter.md delete mode 100644 docs/tools/video/video-capturer.md delete mode 100644 docs/tsconfig.json create mode 100644 gradle/libs.versions.toml delete mode 100644 pom.xml create mode 100644 settings.gradle.kts delete mode 100644 webrtc-examples/pom.xml delete mode 100644 webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/client/SignalingManager.java delete mode 100644 webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/client/WebSocketClient.java delete mode 100644 webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/connection/PeerConnectionManager.java delete mode 100644 webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/connection/PeerConnectionSignalingHandler.java delete mode 100644 webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/model/IceCandidateMessage.java delete mode 100644 webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/model/JoinMessage.java delete mode 100644 webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/model/LeaveMessage.java delete mode 100644 webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/model/MessageType.java delete mode 100644 webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/model/SessionDescriptionMessage.java delete mode 100644 webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/model/SignalingMessage.java delete mode 100644 webrtc-examples/src/main/java/module-info.java delete mode 100644 webrtc-examples/src/main/resources/keystore.p12 delete mode 100644 webrtc-examples/src/main/resources/logging.properties delete mode 100644 webrtc-examples/src/main/resources/web/PeerConnectionManager.js delete mode 100644 webrtc-examples/src/main/resources/web/SignalingChannel.js delete mode 100644 webrtc-examples/src/main/resources/web/WebRTCClient.js delete mode 100644 webrtc-examples/src/main/resources/web/index.html delete mode 100644 webrtc-examples/src/main/resources/web/main.js create mode 100644 webrtc-jni/build.gradle.kts delete mode 100644 webrtc-jni/pom.xml create mode 100644 webrtc/build.gradle.kts delete mode 100644 webrtc/pom.xml diff --git a/.gitignore b/.gitignore index baaf034..83ecbfa 100644 --- a/.gitignore +++ b/.gitignore @@ -15,9 +15,20 @@ *.dylib *.dll +# Gradle +.gradle +**/build/ +!src/**/build/ +gradle-app.setting +!gradle-wrapper.jar +!gradle-wrapper.properties + +# Local sysroot files webrtc-jni/src/main/cpp/dependencies/webrtc/linux/debian*amd64* webrtc-jni/src/main/cpp/dependencies/webrtc/linux/debian*armhf* webrtc-jni/src/main/cpp/dependencies/webrtc/linux/debian*arm64* webrtc-jni/src/main/cpp/dependencies/webrtc/webrtc-source/ + +# VSCode / clangd .cache/ -compile_commands.json \ No newline at end of file +compile_commands.json diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..ded358a --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,23 @@ +plugins { + alias(libs.plugins.nmcp) +} + +allprojects { + group = "dev.onvoid.webrtc" + version = "0.15.0-SNAPSHOT" + + repositories { + mavenCentral() + } +} + +nmcp { + publishAggregation { + project(":webrtc") + + username.set(System.getenv("MAVEN_CENTRAL_USERNAME")) + password.set(System.getenv("MAVEN_CENTRAL_PASSWORD")) + + publicationType.set("AUTOMATIC") + } +} \ No newline at end of file diff --git a/docs/.gitignore b/docs/.gitignore deleted file mode 100644 index 3041a04..0000000 --- a/docs/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -.vitepress/cache -.vitepress/dist - -node_modules \ No newline at end of file diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts deleted file mode 100644 index 0c626a5..0000000 --- a/docs/.vitepress/config.mts +++ /dev/null @@ -1,49 +0,0 @@ -import { defineConfig } from 'vitepress' -import { footer } from "./footer"; -import { head } from "./head"; -import { navbar } from "./nav"; -import { sidebar } from "./sidebar"; -import { PROJECT_VARS } from './versions' - -export default defineConfig({ - title: "webrtc-java", - description: "Java native interface for WebRTC", - cleanUrls: true, - - head: head, - - themeConfig: { - logo: { - light: '/logo.png', - dark: '/logo.png', - alt: 'logo' - }, - - externalLinkIcon: true, - - nav: navbar, - sidebar: sidebar, - footer: footer, - socialLinks: [ - { icon: 'github', link: 'https://github.com/devopvoid/webrtc-java' }, - ], - search: { - provider: 'local', - }, - }, - - markdown: { - config: (md) => { - md.use(variableInterpolationPlugin) - }, - }, -}) - -function variableInterpolationPlugin(md) { - md.core.ruler.after('normalize', 'variable-interpolation', (state) => { - Object.entries(PROJECT_VARS).forEach(([key, value]) => { - const regex = new RegExp(`{{\\s*${key}\\s*}}`, 'g') - state.src = state.src.replace(regex, value) - }) - }) -} diff --git a/docs/.vitepress/footer.ts b/docs/.vitepress/footer.ts deleted file mode 100644 index a6b949d..0000000 --- a/docs/.vitepress/footer.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { DefaultTheme } from "vitepress"; - -export const footer: DefaultTheme.Footer = { - message: 'Released under the Apache-2.0 License.', - copyright: 'Copyright © 2019-present Alex Andres', -} \ No newline at end of file diff --git a/docs/.vitepress/head.ts b/docs/.vitepress/head.ts deleted file mode 100644 index f000979..0000000 --- a/docs/.vitepress/head.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { HeadConfig } from "vitepress/types/shared"; - -const isProd = process.env.NODE_ENV === 'production'; - -const head: HeadConfig[] = [ - ['link', { rel: "icon", type: "image/png", sizes: "96x96", href: "/favicon-96x96.png" }], - ['link', { rel: "icon", type: "image/svg+xml", href: "/favicon.svg" }], - ['link', { rel: "shortcut icon", href: "/favicon.ico" }], - ['link', { rel: "apple-touch-icon", sizes: "180x180", href: "/apple-touch-icon.png" }], - ['link', { rel: "manifest", href: "/site.webmanifest" }], - ['meta', { name: "apple-mobile-web-app-title", content: "JRTC" }], -] - -if (isProd) { - head.push([ - 'script', - { - async: '', - src: 'https://eu.umami.is/script.js', - 'data-website-id': '126654a9-5f07-4b57-ad7e-023eda3980ff', - 'data-domains': 'jrtc.dev', - 'data-do-not-track': 'true' - }, - ]) -} - -export { head } \ No newline at end of file diff --git a/docs/.vitepress/nav.ts b/docs/.vitepress/nav.ts deleted file mode 100644 index a988385..0000000 --- a/docs/.vitepress/nav.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { DefaultTheme } from "vitepress"; -import { PROJECT_VARS } from './versions' - -export const navbar: DefaultTheme.NavItem[] = [ - { - text: 'Guide', - link: '/guide/', - }, - { - text: 'Examples', - link: '/guide/examples', - }, - { - text: 'Tools', - link: '/tools', - }, - { - text: PROJECT_VARS.VERSION, - items: [ - { - text: 'Changelog', - link: 'https://github.com/devopvoid/webrtc-java/blob/main/CHANGELOG.md' - }, - { - text: 'Build Notes', - link: '/guide/build' - } - ] - } -] \ No newline at end of file diff --git a/docs/.vitepress/sidebar.ts b/docs/.vitepress/sidebar.ts deleted file mode 100644 index 402c612..0000000 --- a/docs/.vitepress/sidebar.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { DefaultTheme } from "vitepress"; - -export const sidebar: DefaultTheme.Sidebar = { - '/guide/': { base: '/guide/', items: sidebarGuide() }, - '/tools/': { base: '/tools/', items: sidebarTools() }, -} - -function sidebarGuide(): DefaultTheme.SidebarItem[] { - return [ - { - text: 'Introduction', - collapsed: false, - items: [ - { text: 'What is webrtc-java?', link: '/introduction' }, - { text: 'Getting Started', link: '/get-started' }, - ], - }, - { - text: 'Media Basics', - collapsed: false, - items: [ - { text: 'Media Devices', link: '/media/media-devices' }, - { text: 'Media Constraints', link: '/media/constraints' }, - { text: 'Media Directionality', link: '/media/directionality' }, - ], - }, - { - text: 'Audio', - collapsed: false, - items: [ - { text: 'Audio Devices', link: '/audio/audio-devices' }, - { text: 'Audio Processing', link: '/audio/audio-processing' }, - { text: 'Custom Audio Source', link: '/audio/custom-audio-source' }, - { text: 'Headless Audio', link: '/audio/headless-audio' }, - { text: 'DTMF Sender', link: '/audio/dtmf-sender' }, - ], - }, - { - text: 'Video', - collapsed: false, - items: [ - { text: 'Camera Video', link: '/video/camera-capture' }, - { text: 'Desktop Video', link: '/video/desktop-capture' }, - { text: 'Custom Video Source', link: '/video/custom-video-source' }, - ], - }, - { - text: 'Data Communication', - collapsed: false, - items: [ - { text: 'Data Channels', link: '/data/data-channels' }, - ], - }, - { - text: 'Networking and ICE', - collapsed: false, - items: [ - { text: 'Port Allocator Configuration', link: '/networking/port-allocator-config' }, - ], - }, - { - text: 'Monitoring and Debugging', - collapsed: false, - items: [ - { text: 'RTC Stats', link: '/monitoring/rtc-stats' }, - { text: 'Logging', link: '/monitoring/logging' }, - ], - }, - ] -} - -function sidebarTools(): DefaultTheme.SidebarItem[] { - return [ - { - text: 'Audio', - collapsed: false, - items: [ - { text: 'Audio Converter', link: '/audio/audio-converter' }, - { text: 'Audio Recorder', link: '/audio/audio-recorder' }, - { text: 'Audio Player', link: '/audio/audio-player' }, - { text: 'Voice Activity Detector', link: '/audio/voice-activity-detector' }, - ], - }, - { - text: 'Video', - collapsed: false, - items: [ - { text: 'Video Buffer Converter', link: '/video/video-buffer-converter' }, - { text: 'Video Capture', link: '/video/video-capturer' }, - ], - }, - { - text: 'Desktop', - collapsed: false, - items: [ - { text: 'Screen Capturer', link: '/desktop/screen-capturer' }, - { text: 'Window Capturer ', link: '/desktop/window-capturer' }, - { text: 'Power Management', link: '/desktop/power-management' }, - ], - }, - ] -} \ No newline at end of file diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts deleted file mode 100644 index def4cfc..0000000 --- a/docs/.vitepress/theme/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -// https://vitepress.dev/guide/custom-theme -import { h } from 'vue' -import type { Theme } from 'vitepress' -import DefaultTheme from 'vitepress/theme' -import './style.css' - -export default { - extends: DefaultTheme, - Layout: () => { - return h(DefaultTheme.Layout, null, { - // https://vitepress.dev/guide/extending-default-theme#layout-slots - }) - }, - enhanceApp({ app, router, siteData }) { - // ... - } -} satisfies Theme diff --git a/docs/.vitepress/theme/style.css b/docs/.vitepress/theme/style.css deleted file mode 100644 index 329e989..0000000 --- a/docs/.vitepress/theme/style.css +++ /dev/null @@ -1,139 +0,0 @@ -/** - * Customize default theme styling by overriding CSS variables: - * https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css - */ - -/** - * Colors - * - * Each colors have exact same color scale system with 3 levels of solid - * colors with different brightness, and 1 soft color. - * - * - `XXX-1`: The most solid color used mainly for colored text. It must - * satisfy the contrast ratio against when used on top of `XXX-soft`. - * - * - `XXX-2`: The color used mainly for hover state of the button. - * - * - `XXX-3`: The color for solid background, such as bg color of the button. - * It must satisfy the contrast ratio with pure white (#ffffff) text on - * top of it. - * - * - `XXX-soft`: The color used for subtle background such as custom container - * or badges. It must satisfy the contrast ratio when putting `XXX-1` colors - * on top of it. - * - * The soft color must be semi transparent alpha channel. This is crucial - * because it allows adding multiple "soft" colors on top of each other - * to create an accent, such as when having inline code block inside - * custom containers. - * - * - `default`: The color used purely for subtle indication without any - * special meanings attached to it such as bg color for menu hover state. - * - * - `brand`: Used for primary brand colors, such as link text, button with - * brand theme, etc. - * - * - `tip`: Used to indicate useful information. The default theme uses the - * brand color for this by default. - * - * - `warning`: Used to indicate warning to the users. Used in custom - * container, badges, etc. - * - * - `danger`: Used to show error, or dangerous message to the users. Used - * in custom container, badges, etc. - * -------------------------------------------------------------------------- */ - -:root { - --vp-c-default-1: var(--vp-c-gray-1); - --vp-c-default-2: var(--vp-c-gray-2); - --vp-c-default-3: var(--vp-c-gray-3); - --vp-c-default-soft: var(--vp-c-gray-soft); - - --vp-c-brand-1: var(--vp-c-indigo-1); - --vp-c-brand-2: var(--vp-c-indigo-2); - --vp-c-brand-3: var(--vp-c-indigo-3); - --vp-c-brand-soft: var(--vp-c-indigo-soft); - - --vp-c-tip-1: var(--vp-c-brand-1); - --vp-c-tip-2: var(--vp-c-brand-2); - --vp-c-tip-3: var(--vp-c-brand-3); - --vp-c-tip-soft: var(--vp-c-brand-soft); - - --vp-c-warning-1: var(--vp-c-yellow-1); - --vp-c-warning-2: var(--vp-c-yellow-2); - --vp-c-warning-3: var(--vp-c-yellow-3); - --vp-c-warning-soft: var(--vp-c-yellow-soft); - - --vp-c-danger-1: var(--vp-c-red-1); - --vp-c-danger-2: var(--vp-c-red-2); - --vp-c-danger-3: var(--vp-c-red-3); - --vp-c-danger-soft: var(--vp-c-red-soft); -} - -/** - * Component: Button - * -------------------------------------------------------------------------- */ - -:root { - --vp-button-brand-border: transparent; - --vp-button-brand-text: var(--vp-c-white); - --vp-button-brand-bg: var(--vp-c-brand-3); - --vp-button-brand-hover-border: transparent; - --vp-button-brand-hover-text: var(--vp-c-white); - --vp-button-brand-hover-bg: var(--vp-c-brand-2); - --vp-button-brand-active-border: transparent; - --vp-button-brand-active-text: var(--vp-c-white); - --vp-button-brand-active-bg: var(--vp-c-brand-1); -} - -/** - * Component: Home - * -------------------------------------------------------------------------- */ - -:root { - --vp-home-hero-name-color: transparent; - --vp-home-hero-name-background: -webkit-linear-gradient( - 120deg, - #1d4ed8 30%, - #1e3a8a - ); - - --vp-home-hero-image-background-image: linear-gradient( - -45deg, - #60a5fa 50%, - #1d4ed8 50% - ); - --vp-home-hero-image-filter: blur(44px); -} - -@media (min-width: 640px) { - :root { - --vp-home-hero-image-filter: blur(56px); - } -} - -@media (min-width: 960px) { - :root { - --vp-home-hero-image-filter: blur(68px); - } -} - -/** - * Component: Custom Block - * -------------------------------------------------------------------------- */ - -:root { - --vp-custom-block-tip-border: transparent; - --vp-custom-block-tip-text: var(--vp-c-text-1); - --vp-custom-block-tip-bg: var(--vp-c-brand-soft); - --vp-custom-block-tip-code-bg: var(--vp-c-brand-soft); -} - -/** - * Component: Algolia - * -------------------------------------------------------------------------- */ - -.DocSearch { - --docsearch-primary-color: var(--vp-c-brand-1) !important; -} - diff --git a/docs/.vitepress/versions.ts b/docs/.vitepress/versions.ts deleted file mode 100644 index dd942dc..0000000 --- a/docs/.vitepress/versions.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const PROJECT_VARS: Record = { - VERSION: '0.14.0', - VERSION_SNAPSHOT: '0.15.0-SNAPSHOT' -}; \ No newline at end of file diff --git a/docs/guide/audio/audio-devices.md b/docs/guide/audio/audio-devices.md deleted file mode 100644 index 16d6669..0000000 --- a/docs/guide/audio/audio-devices.md +++ /dev/null @@ -1,140 +0,0 @@ -# Audio Devices - -This guide focuses on setting up a peer connection with audio device selection capabilities, which allows you to choose specific microphones and speakers for your WebRTC connection. - -## Audio Device Selection - -To enable audio device selection, you need to: - -1. List available audio devices -2. Create and configure an `AudioDeviceModule` -3. Pass the `AudioDeviceModule` to the `PeerConnectionFactory` - -### Listing Available Audio Devices - -The `MediaDevices` class provides methods to list available audio devices: - -```java -import dev.onvoid.webrtc.media.MediaDevices; -import dev.onvoid.webrtc.media.audio.AudioDevice; -import java.util.List; - -// Get available microphones (capture devices) -List captureDevices = MediaDevices.getAudioCaptureDevices(); -System.out.println("Available microphones:"); -for (AudioDevice device : captureDevices) { - System.out.println(" - " + device.getName()); -} - -// Get available speakers (render devices) -List renderDevices = MediaDevices.getAudioRenderDevices(); -System.out.println("Available speakers:"); -for (AudioDevice device : renderDevices) { - System.out.println(" - " + device.getName()); -} - -// Get default devices -AudioDevice defaultMicrophone = MediaDevices.getDefaultAudioCaptureDevice(); -AudioDevice defaultSpeaker = MediaDevices.getDefaultAudioRenderDevice(); -``` - -### Creating and Configuring an AudioDeviceModule - -The `AudioDeviceModule` class allows you to select specific audio devices: - -```java -import dev.onvoid.webrtc.media.audio.AudioDeviceModule; - -// Create an AudioDeviceModule -AudioDeviceModule audioModule = new AudioDeviceModule(); - -// Select specific devices -AudioDevice selectedMicrophone = captureDevices.get(0); // Choose the first microphone -AudioDevice selectedSpeaker = renderDevices.get(0); // Choose the first speaker - -audioModule.setRecordingDevice(selectedMicrophone); -audioModule.setPlayoutDevice(selectedSpeaker); - -// Initialize recording and playback -audioModule.initRecording(); -audioModule.initPlayout(); -``` - -### Integrating with PeerConnectionFactory - -Pass the configured AudioDeviceModule to the PeerConnectionFactory constructor: - -```java -// Create a PeerConnectionFactory with the custom AudioDeviceModule -PeerConnectionFactory factory = new PeerConnectionFactory(audioModule); -``` - - -## Disabling Audio - -If you want to completely disable audio processing in your WebRTC application, you can create an AudioDeviceModule with the `kDummyAudio` layer: - -```java -import dev.onvoid.webrtc.media.audio.AudioDeviceModule; -import dev.onvoid.webrtc.media.audio.AudioLayer; - -// Create an AudioDeviceModule with dummy audio (no real audio processing) -AudioDeviceModule audioModule = new AudioDeviceModule(AudioLayer.kDummyAudio); - -// Pass it to the PeerConnectionFactory -PeerConnectionFactory factory = new PeerConnectionFactory(audioModule); -``` - -This is useful for applications that only need video functionality, when you want to implement your own custom audio handling, or for headless modes where neither audio nor video is required. Using the dummy audio layer is particularly valuable in server-side or automated testing environments where no physical audio devices are available. - -## Additional Features - -The `AudioDeviceModule` provides additional methods for controlling audio: - -### Volume Control -```java -// Get current volume levels -int micVolume = audioModule.getMicrophoneVolume(); -int speakerVolume = audioModule.getSpeakerVolume(); - -// Get volume ranges -int minMicVolume = audioModule.getMinMicrophoneVolume(); -int maxMicVolume = audioModule.getMaxMicrophoneVolume(); -int minSpeakerVolume = audioModule.getMinSpeakerVolume(); -int maxSpeakerVolume = audioModule.getMaxSpeakerVolume(); - -// Set volume levels -audioModule.setMicrophoneVolume(75); // Set to 75% of max -audioModule.setSpeakerVolume(80); // Set to 80% of max -``` - -### Mute Control -```java -// Check mute status -boolean isMicMuted = audioModule.isMicrophoneMuted(); -boolean isSpeakerMuted = audioModule.isSpeakerMuted(); - -// Set mute status -audioModule.setMicrophoneMute(true); // Mute microphone -audioModule.setSpeakerMute(false); // Unmute speaker -``` - -### Device Change Handling -```java -// Add a device change listener to handle device hot-plugging -MediaDevices.addDeviceChangeListener(event -> { - System.out.println("Audio devices changed. Refreshing device list..."); - - // Refresh device lists - List newCaptureDevices = MediaDevices.getAudioCaptureDevices(); - List newRenderDevices = MediaDevices.getAudioRenderDevices(); - - // Update UI or device selection as needed -}); -``` - -## Conclusion - -This guide has walked you through the process of implementing audio device selection in your WebRTC application. -By implementing these capabilities, your application can provide users with greater control over their audio experience, accommodating different hardware setups and preferences. -For more advanced audio processing options, consider exploring the audio processing APIs available in this documentation. \ No newline at end of file diff --git a/docs/guide/audio/audio-processing.md b/docs/guide/audio/audio-processing.md deleted file mode 100644 index 92d5c29..0000000 --- a/docs/guide/audio/audio-processing.md +++ /dev/null @@ -1,340 +0,0 @@ -# Audio Processing - -This guide explains how to use the audio processing capabilities provided by the `dev.onvoid.webrtc.media.audio.AudioProcessing` class. The library provides a collection of voice processing components designed for real-time communications software. - -## Overview - -The `AudioProcessing` class offers several audio processing features: - -- **Echo Cancellation**: Removes echo from audio signals -- **Noise Suppression**: Reduces background noise -- **Gain Control**: Adjusts audio levels automatically -- **High-Pass Filtering**: Removes low-frequency noise - -These features are particularly useful for VoIP applications, video conferencing, and other real-time communication systems. - -## Two Approaches to Audio Processing - -There are two main approaches to using audio processing in the library: - -1. **Automatic Processing with PeerConnectionFactory**: Set a configured `AudioProcessing` instance to the `PeerConnectionFactory`. This is the recommended approach for most applications. -2. **Manual Processing**: Create an `AudioProcessing` instance and manually process audio streams. This gives you more control but requires more work. - -### Automatic Processing with PeerConnectionFactory - -The simplest way to use audio processing is to set a configured `AudioProcessing` instance to the `PeerConnectionFactory`: - -```java -import dev.onvoid.webrtc.PeerConnectionFactory; -import dev.onvoid.webrtc.media.audio.AudioProcessing; -import dev.onvoid.webrtc.media.audio.AudioProcessingConfig; -import dev.onvoid.webrtc.media.audio.NoiseSuppression; - -// Create and configure an AudioProcessing instance -AudioProcessing audioProcessing = new AudioProcessing(); -AudioProcessingConfig config = new AudioProcessingConfig(); - -// Enable echo cancellation -config.echoCanceller.enabled = true; - -// Enable noise suppression -config.noiseSuppression.enabled = true; -config.noiseSuppression.level = NoiseSuppression.Level.MODERATE; - -// Apply the configuration -audioProcessing.applyConfig(config); - -// Create a PeerConnectionFactory with the configured AudioProcessing -PeerConnectionFactory factory = new PeerConnectionFactory(audioProcessing); - -// Now all audio processing will be handled automatically by the WebRTC framework -// ... - -// Don't forget to dispose when done -factory.dispose(); -audioProcessing.dispose(); -``` - -With this approach, the WebRTC framework automatically applies the audio processing to all audio streams. You don't need to manually process audio data - the WebRTC framework handles it internally based on your configuration. - -### Manual Processing - -For more control, you can manually process audio streams: - -```java -import dev.onvoid.webrtc.media.audio.AudioProcessing; -import dev.onvoid.webrtc.media.audio.AudioProcessingConfig; -import dev.onvoid.webrtc.media.audio.AudioProcessingStreamConfig; - -// Create an AudioProcessing instance -AudioProcessing audioProcessing = new AudioProcessing(); - -try { - // Configure audio processing - AudioProcessingConfig config = new AudioProcessingConfig(); - - audioProcessing.applyConfig(config); - - // Process audio streams - // ... -} finally { - // Always dispose when done to release native resources - audioProcessing.dispose(); -} -``` - -## Configuration - -The `AudioProcessingConfig` class allows you to enable and configure various audio processing features: - -### Echo Cancellation - -Echo cancellation removes echo from audio signals, which is essential for full-duplex audio communication: - -```java -AudioProcessingConfig config = new AudioProcessingConfig(); - -// Enable echo cancellation -config.echoCanceller.enabled = true; - -// Enable high-pass filtering during echo cancellation -config.echoCanceller.enforceHighPassFiltering = true; -``` - -When echo cancellation is enabled, you should set the stream delay to help the echo canceller: - -```java -// Set the delay between far-end and near-end audio in milliseconds -audioProcessing.setStreamDelayMs(70); -``` - -### Noise Suppression - -Noise suppression reduces background noise in the audio signal: - -```java -// Enable noise suppression -config.noiseSuppression.enabled = true; - -// Set the level of noise suppression -// Options: LOW, MODERATE, HIGH, VERY_HIGH -config.noiseSuppression.level = NoiseSuppression.Level.MODERATE; -``` - -### Gain Control - -Gain control adjusts the audio level automatically. WebRTC provides two gain controllers: -- GainController (AGC1, legacy/classic) -- GainControllerDigital (newer digital AGC) - -In most applications you should enable only one of them at a time. - -#### Legacy Gain Controller (AGC1) -AGC1 can operate in analog or digital modes and includes an optional limiter. - -```java -// Enable the legacy AGC1 -config.gainController.enabled = true; - -// Select mode: AdaptiveAnalog, AdaptiveDigital, or FixedDigital -config.gainController.mode = AudioProcessingConfig.GainController.Mode.AdaptiveAnalog; - -// Set the target level (in dBFS) and compression gain (in dB) -config.gainController.targetLevelDbfs = 3; // common default -config.gainController.compressionGainDb = 9; // common default - -// Enable the limiter to reduce clipping -config.gainController.enableLimiter = true; - -// Optional: tune analog gain controller sub-settings -config.gainController.analogGainController.enabled = true; -config.gainController.analogGainController.enableDigitalAdaptive = true; -// Clipping predictor (optional) -config.gainController.analogGainController.clippingPredictor.enabled = false; -``` - -When using AdaptiveAnalog mode, integrate with your system microphone level if possible so AGC1 can adjust the hardware/OS capture volume. Use AdaptiveDigital if you cannot control device gain. FixedDigital applies a constant digital gain. - -#### Digital Gain Controller - -```java -// Enable the newer digital AGC -config.gainControllerDigital.enabled = true; - -// Configure fixed digital gain (in dB) -config.gainControllerDigital.fixedDigital.gainDb = 5.0f; - -// Or configure adaptive digital gain -config.gainControllerDigital.adaptiveDigital.enabled = true; -config.gainControllerDigital.adaptiveDigital.headroomDb = 3.0f; -config.gainControllerDigital.adaptiveDigital.maxGainDb = 30.0f; -config.gainControllerDigital.adaptiveDigital.initialGainDb = 8.0f; -config.gainControllerDigital.adaptiveDigital.maxGainChangeDbPerSecond = 3.0f; -config.gainControllerDigital.adaptiveDigital.maxOutputNoiseLevelDbfs = -50.0f; -``` - -### High-Pass Filter - -High-pass filtering removes low-frequency noise: - -```java -// Enable high-pass filtering -config.highPassFilter.enabled = true; -``` - -## Processing Audio - -The `AudioProcessing` class processes audio in 10ms chunks of linear PCM audio data. You need to configure the input and output formats using `AudioProcessingStreamConfig`: - -```java -// Define input and output stream configurations -int inputSampleRate = 48000; // 48 kHz -int inputChannels = 1; // Mono -int outputSampleRate = 48000; // 48 kHz -int outputChannels = 1; // Mono - -AudioProcessingStreamConfig inputConfig = - new AudioProcessingStreamConfig(inputSampleRate, inputChannels); -AudioProcessingStreamConfig outputConfig = - new AudioProcessingStreamConfig(outputSampleRate, outputChannels); -``` - -### Calculate Buffer Size - -Before processing, you need to calculate the appropriate buffer size: - -```java -// Calculate buffer size for destination buffer -int bufferSize = audioProcessing.getTargetBufferSize(inputConfig, outputConfig); - -// Create source and destination buffers -byte[] sourceBuffer = new byte[inputSampleRate / 100 * inputChannels * 2]; // 10ms of audio -byte[] destBuffer = new byte[bufferSize]; -``` - -### Process Near-End Audio - -Process audio captured from the local microphone: - -```java -// Fill sourceBuffer with audio data from microphone -// ... - -// Process the audio -int result = audioProcessing.processStream( - sourceBuffer, inputConfig, outputConfig, destBuffer); - -// Check result (0 means success) -if (result == 0) { - // Use processed audio in destBuffer - // ... -} -``` - -### Process Far-End Audio - -For echo cancellation, you also need to process audio received from the remote end: - -```java -// Fill sourceBuffer with audio data from remote participant -// ... - -// Process the far-end audio -int result = audioProcessing.processReverseStream( - sourceBuffer, inputConfig, outputConfig, destBuffer); - -// Check result (0 means success) -if (result == 0) { - // Use processed audio in destBuffer (usually for playback) - // ... -} -``` - -## Format Conversion - -The `AudioProcessing` class can also convert between different audio formats: - -### Down-mixing (Stereo to Mono) - -```java -// Configure for down-mixing -AudioProcessingStreamConfig stereoConfig = - new AudioProcessingStreamConfig(48000, 2); // Stereo input -AudioProcessingStreamConfig monoConfig = - new AudioProcessingStreamConfig(48000, 1); // Mono output - -// Process with format conversion -audioProcessing.processStream( - stereoBuffer, stereoConfig, monoConfig, monoDestBuffer); -``` - -### Up-mixing (Mono to Stereo) - -```java -// Configure for up-mixing -AudioProcessingStreamConfig monoConfig = - new AudioProcessingStreamConfig(48000, 1); // Mono input -AudioProcessingStreamConfig stereoConfig = - new AudioProcessingStreamConfig(48000, 2); // Stereo output - -// Process with format conversion -audioProcessing.processStream( - monoBuffer, monoConfig, stereoConfig, stereoDestBuffer); -``` - -### Sample Rate Conversion - -```java -// Configure for sample rate conversion -AudioProcessingStreamConfig highRateConfig = - new AudioProcessingStreamConfig(48000, 1); // 48 kHz -AudioProcessingStreamConfig lowRateConfig = - new AudioProcessingStreamConfig(16000, 1); // 16 kHz - -// Process with sample rate conversion -audioProcessing.processStream( - highRateBuffer, highRateConfig, lowRateConfig, lowRateDestBuffer); -``` - -## Statistics - -The `AudioProcessing` class provides statistics about the audio processing performance: - -```java -// Get statistics -AudioProcessingStats stats = audioProcessing.getStatistics(); - -// Echo cancellation statistics -System.out.println("Echo Return Loss: " + stats.echoReturnLoss + " dB"); -System.out.println("Echo Return Loss Enhancement: " + stats.echoReturnLossEnhancement + " dB"); -System.out.println("Divergent Filter Fraction: " + stats.divergentFilterFraction); - -// Delay statistics -System.out.println("Current Delay: " + stats.delayMs + " ms"); -System.out.println("Median Delay: " + stats.delayMedianMs + " ms"); -System.out.println("Delay Standard Deviation: " + stats.delayStandardDeviationMs + " ms"); - -// Residual echo statistics -System.out.println("Residual Echo Likelihood: " + stats.residualEchoLikelihood); -System.out.println("Recent Max Residual Echo Likelihood: " + stats.residualEchoLikelihoodRecentMax); -``` - -These statistics are particularly useful for monitoring the performance of echo cancellation. - -## Best Practices - -1. **Always dispose**: Call `dispose()` when you're done with the `AudioProcessing` instance to free native resources. - -2. **Configure before processing**: Apply your configuration before processing any audio for best results. - -3. **Set stream delay**: For echo cancellation to work effectively, set the stream delay using `setStreamDelayMs()`. - -4. **Process in 10ms chunks**: The audio processing is designed to work with 10ms chunks of audio. - -5. **Monitor statistics**: Use the statistics to monitor the performance of echo cancellation and adjust settings if needed. - -## Conclusion - -The `AudioProcessing` class provides powerful audio processing capabilities for real-time communications. By properly configuring and using these features, you can significantly improve the audio quality in your applications. - -Remember that audio processing is CPU-intensive, so consider the performance implications when enabling multiple features, especially on resource-constrained devices. \ No newline at end of file diff --git a/docs/guide/audio/custom-audio-source.md b/docs/guide/audio/custom-audio-source.md deleted file mode 100644 index 33d90a6..0000000 --- a/docs/guide/audio/custom-audio-source.md +++ /dev/null @@ -1,190 +0,0 @@ -# Custom Audio Source - -This guide explains how to use the `CustomAudioSource` class to push audio data from external sources directly to the WebRTC audio pipeline. - -## Overview - -The `CustomAudioSource` allows you to provide audio data from custom sources such as: -- Audio files -- Network streams -- Generated audio (tones, noise, etc.) -- Audio processing libraries -- Any other source of raw audio data - -This is particularly useful when you need to: -- Stream pre-recorded audio -- Process audio before sending it -- Generate synthetic audio -- Integrate with external audio APIs - -## Basic Usage - -### Creating a Custom Audio Source - -To use a custom audio source, you first need to create an instance: - -```java -import dev.onvoid.webrtc.media.audio.CustomAudioSource; - -// Create a new CustomAudioSource instance -CustomAudioSource audioSource = new CustomAudioSource(); -``` - -### Creating an Audio Track - -Once you have a custom audio source, you can create an audio track with it: - -```java -import dev.onvoid.webrtc.PeerConnectionFactory; -import dev.onvoid.webrtc.media.audio.AudioTrack; - -// Create a PeerConnectionFactory (you should already have this in your WebRTC setup) -PeerConnectionFactory factory = new PeerConnectionFactory(); - -// Create an audio track using the custom audio source -AudioTrack audioTrack = factory.createAudioTrack("audio-track-id", audioSource); -``` - -### Pushing Audio Data - -The key feature of `CustomAudioSource` is the ability to push audio data directly to the WebRTC pipeline: - -```java -// Parameters for the audio data -int bitsPerSample = 16; // Common values: 8, 16, 32 -int sampleRate = 48000; // Common values: 8000, 16000, 44100, 48000 -int channels = 2; // 1 for mono, 2 for stereo -int frameCount = 480; // For 10ms of audio at 48kHz - -// Create a buffer for the audio data -// Size = frameCount * channels * (bitsPerSample / 8) -int bytesPerSample = bitsPerSample / 8; -byte[] audioData = new byte[frameCount * channels * bytesPerSample]; - -// Fill the buffer with your audio data -// ... - -// Push the audio data to the WebRTC pipeline -audioSource.pushAudio(audioData, bitsPerSample, sampleRate, channels, frameCount); -``` - -## Audio Format Considerations - -When pushing audio data, you need to consider the following parameters: - -### Bits Per Sample -- **8-bit**: Lower quality, smaller data size -- **16-bit**: Standard quality for most applications -- **32-bit**: Higher quality, larger data size - -### Sample Rate -- **8000 Hz**: Telephone quality -- **16000 Hz**: Good for speech -- **44100 Hz**: CD quality -- **48000 Hz**: Standard for digital audio workstations and professional audio - -### Channels -- **1 (Mono)**: Single channel audio -- **2 (Stereo)**: Dual channel audio - -### Frame Count -The number of frames depends on the desired buffer size and sample rate. For a 10ms buffer: -- At 8000 Hz: 80 frames -- At 16000 Hz: 160 frames -- At 44100 Hz: 441 frames -- At 48000 Hz: 480 frames - -## Advanced Usage - -### Continuous Audio Streaming - -For continuous streaming, you'll typically push audio data in a separate thread: - -```java -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -public class AudioStreamer { - private final CustomAudioSource audioSource; - private final ScheduledExecutorService executor; - private final int bitsPerSample = 16; - private final int sampleRate = 48000; - private final int channels = 2; - private final int frameCount = 480; // 10ms at 48kHz - - public AudioStreamer(CustomAudioSource audioSource) { - this.audioSource = audioSource; - this.executor = Executors.newSingleThreadScheduledExecutor(); - } - - public void start() { - // Schedule task to run every 10ms - executor.scheduleAtFixedRate(this::pushNextAudioBuffer, 0, 10, TimeUnit.MILLISECONDS); - } - - public void stop() { - executor.shutdown(); - } - - private void pushNextAudioBuffer() { - // Create and fill audio buffer - int bytesPerSample = bitsPerSample / 8; - byte[] audioData = new byte[frameCount * channels * bytesPerSample]; - - // Fill audioData with your audio samples - // ... - - // Push to WebRTC - audioSource.pushAudio(audioData, bitsPerSample, sampleRate, channels, frameCount); - } -} -``` - -## Integration with Audio Tracks - -### Adding Sinks to Monitor Audio - -You can add sinks to the audio track to monitor the audio data: - -```java -import dev.onvoid.webrtc.media.audio.AudioTrackSink; - -// Create a sink to monitor the audio data -AudioTrackSink monitorSink = (data, bitsPerSample, sampleRate, channels, frames) -> { - System.out.println("Received audio: " + - bitsPerSample + " bits, " + - sampleRate + " Hz, " + - channels + " channels, " + - frames + " frames"); - - // You can process or analyze the audio data here -}; - -// Add the sink to the audio track -audioTrack.addSink(monitorSink); - -// When done, remove the sink -audioTrack.removeSink(monitorSink); -``` - -## Cleanup - -When you're done with the custom audio source, make sure to clean up resources: - -```java -// Dispose of the audio track -audioTrack.dispose(); - -// Dispose of the audio source to prevent memory leaks -audioSource.dispose(); - -// If you're using a scheduled executor for pushing audio -audioStreamer.stop(); -``` - -## Conclusion - -The `CustomAudioSource` provides a flexible way to integrate external audio sources with WebRTC. By understanding the audio format parameters and properly managing the audio data flow, you can create applications that use custom audio from virtually any source. - -For more advanced audio processing options, consider exploring the audio processing APIs available in this documentation. \ No newline at end of file diff --git a/docs/guide/audio/dtmf-sender.md b/docs/guide/audio/dtmf-sender.md deleted file mode 100644 index 0b2b7bf..0000000 --- a/docs/guide/audio/dtmf-sender.md +++ /dev/null @@ -1,164 +0,0 @@ -# DTMF Sender - -This guide explains how to use the DTMF (Dual-Tone Multi-Frequency) sender functionality with the webrtc-java library. DTMF senders allow you to send DTMF tones over WebRTC audio connections, which is useful for interactive voice response (IVR) systems and telephony applications. - -## Overview - -WebRTC DTMF senders allow you to: -- Send DTMF tones over an established audio connection -- Configure tone duration and inter-tone gap -- Monitor tone transmission events -- Check if DTMF tones can be inserted - -DTMF tones are the audible tones generated when pressing keys on a telephone keypad. The supported DTMF tones are: 0-9, A-D, *, and #. In addition, the special character ',' (comma) can be used to insert a 2-second delay between tones. - -## Getting a DTMF Sender - -To use DTMF functionality, you need an established `RTCPeerConnection` with an audio track. You can then get the DTMF sender from the RTP sender associated with the audio track: - -```java -import dev.onvoid.webrtc.RTCPeerConnection; -import dev.onvoid.webrtc.RTCRtpSender; -import dev.onvoid.webrtc.RTCDtmfSender; -import dev.onvoid.webrtc.media.audio.AudioTrack; - -// Assuming you already have a PeerConnectionFactory and RTCConfiguration -RTCPeerConnection peerConnection = factory.createPeerConnection(config, peerConnectionObserver); - -// Create and add an audio track -AudioTrackSource audioSource = factory.createAudioSource(new AudioOptions()); -AudioTrack audioTrack = factory.createAudioTrack("audioTrack", audioSource); - -// Add the track to the peer connection -List streamIds = new ArrayList<>(); -streamIds.add("stream1"); -RTCRtpSender sender = peerConnection.addTrack(audioTrack, streamIds); - -// Get the DTMF sender -RTCDtmfSender dtmfSender = sender.getDtmfSender(); -``` - -## Checking DTMF Capability - -Before attempting to send DTMF tones, you should check if the DTMF sender is capable of sending tones: - -```java -if (dtmfSender != null && dtmfSender.canInsertDtmf()) { - // DTMF is supported and can be used - System.out.println("DTMF is supported"); -} else { - // DTMF is not supported - System.out.println("DTMF is not supported"); -} -``` - -The `canInsertDtmf()` method returns true if and only if: -- The associated RTCRtpSender's track is non-null and is of kind "audio" -- The RTCDtmfSender is able to send packets -- A "telephone-event" codec has been negotiated - -## Sending DTMF Tones - -To send DTMF tones, use the `insertDtmf` method: - -```java -// Send DTMF tones with custom duration (100ms) and inter-tone gap (70ms) -boolean success = dtmfSender.insertDtmf("123", 100, 70); -``` - -The `insertDtmf` method takes the following parameters: -- `tones`: A string containing the DTMF tones to send -- `duration`: The duration in milliseconds for each tone (default: 100ms) -- `interToneGap`: The gap between tones in milliseconds (default: 50ms) - -The method returns `true` if the tones were successfully queued for transmission, or `false` if the operation failed. - -### Valid Tones - -The following characters are valid in the `tones` parameter: -- Digits: 0-9 -- Letters: A-D (or a-d, case-insensitive) -- Symbols: * (asterisk), # (pound/hash) -- Special: , (comma) - inserts a 2-second delay - -Unrecognized characters are ignored. - -### Duration and Inter-Tone Gap Constraints - -The duration and inter-tone gap parameters have the following constraints: -- Duration must be between 70ms and 6000ms (default: 100ms) -- Inter-tone gap must be at least 50ms (default: 50ms) - -If these constraints are not met, the `insertDtmf` method will return `false`. - -## Monitoring DTMF Events - -To receive notifications about DTMF tone events, implement the `RTCDtmfSenderObserver` interface and register it with the DTMF sender: - -```java -import dev.onvoid.webrtc.RTCDtmfSenderObserver; - -dtmfSender.registerObserver(new RTCDtmfSenderObserver() { - @Override - public void onToneChange(String tone, String toneBuffer) { - if (tone == null || tone.isEmpty()) { - System.out.println("All tones have been played"); - } else { - System.out.println("Playing tone: " + tone); - System.out.println("Remaining tones: " + toneBuffer); - } - } -}); -``` - -The `onToneChange` method is called: -- When a new tone starts playing, with the tone character and the remaining tones buffer -- When all tones have finished playing, with an empty string for both parameters - -## Getting DTMF Properties - -You can query various properties of the DTMF sender: - -```java -// Get the tones currently in the queue -String remainingTones = dtmfSender.tones(); - -// Get the current duration setting -int duration = dtmfSender.duration(); - -// Get the current inter-tone gap setting -int interToneGap = dtmfSender.interToneGap(); -``` - -## Cleanup - -When you're done with the DTMF sender, you should unregister any observers: - -```java -// Unregister the observer -dtmfSender.unregisterObserver(); -``` - -Note that you don't need to explicitly dispose of the DTMF sender, as it will be cleaned up when the associated RTP sender is disposed. - -## Best Practices - -1. **Check Capability**: Always check if DTMF is supported using `canInsertDtmf()` before attempting to send tones. - -2. **Error Handling**: Check the return value of `insertDtmf()` to ensure the tones were successfully queued. - -3. **Observer Cleanup**: Always unregister observers when you're done to prevent memory leaks. - -4. **Tone Duration**: Use appropriate tone durations based on your application needs: - - For standard telephony applications, the default 100ms is usually sufficient - - For IVR systems that might need more processing time, consider longer durations - -5. **Tone Buffering**: Be aware that tones are queued and played sequentially. If you need to cancel queued tones, you can call `insertDtmf("")` to clear the queue. - -## Conclusion - -The RTCDtmfSender provides a standard way to send DTMF tones over WebRTC audio connections. This functionality is particularly useful for applications that need to interact with traditional telephony systems, IVR systems, or any service that uses DTMF for signaling. - -By following the guidelines in this document, you can effectively integrate DTMF functionality into your WebRTC applications, enabling users to interact with automated systems or trigger actions using their device's keypad. - -For more information on other WebRTC features, refer to the additional guides in the documentation. \ No newline at end of file diff --git a/docs/guide/audio/headless-audio.md b/docs/guide/audio/headless-audio.md deleted file mode 100644 index 35a5132..0000000 --- a/docs/guide/audio/headless-audio.md +++ /dev/null @@ -1,107 +0,0 @@ -# Headless Audio - -The `HeadlessAudioDeviceModule` is a convenience implementation of the `AudioDeviceModule` that uses WebRTC's dummy audio layer. It avoids touching real OS audio devices while still enabling the WebRTC audio pipeline to pull and render audio frames (headless playout) and to simulate capture (recording path). - -This is ideal for: -- Server-side or CI environments without audio hardware -- Automated tests where deterministic, no-op audio IO is desired -- Receive-only applications that should render audio via the WebRTC pipeline without producing audible output -- Applications that implement custom audio ingestion but do not want to interact with system devices - -## Key characteristics -- Uses dummy audio drivers; no real system devices are opened -- Exposes at least one dummy playout and recording device to allow initialization -- Supports playout and recording initialization and start/stop lifecycle -- Intended primarily for headless scenarios where you want the WebRTC audio pipelines to run without touching physical devices - ---- - -## Playout path - -Create the module and pass it to the `PeerConnectionFactory`. This ensures your peer connection stack uses a headless (dummy) audio backend. - -```java -import dev.onvoid.webrtc.PeerConnectionFactory; -import dev.onvoid.webrtc.media.audio.HeadlessAudioDeviceModule; - -// Create the headless ADM -HeadlessAudioDeviceModule audioModule = new HeadlessAudioDeviceModule(); - -// Initialize and start playout -audioModule.initPlayout(); -audioModule.startPlayout(); - -// Create a factory that uses the headless ADM -PeerConnectionFactory factory = new PeerConnectionFactory(audioModule); - -// ... use the factory to build peer connections ... - -// Cleanup -try { - audioModule.stopPlayout(); -} -catch (Throwable e) { - // Ignore errors during stopPlayout() -} -finally { - audioModule.dispose(); - factory.dispose(); -} -``` - -::: info -- Calling startPlayout without a prior initPlayout will throw an error. Always call initPlayout first. -- If you only need the audio pipeline to be ready when remote audio arrives, you may delay playout initialization until after creating your RTCPeerConnection. -::: - - -## Recording path (capture) - -The headless module also implements a recording path that simulates a microphone. When started, it periodically pulls 10 ms of PCM from the registered AudioTransport (your Java audio source) and feeds it into WebRTC’s capture pipeline. This is particularly useful in tests or server-side senders. - -Typical steps: - -```java -HeadlessAudioDeviceModule adm = new HeadlessAudioDeviceModule(); - -// Initialize and start the recording pipeline (capture) -adm.initRecording(); -adm.startRecording(); - -PeerConnectionFactory factory = new PeerConnectionFactory(adm); - -// Use a custom or built-in AudioSource to provide audio frames -CustomAudioSource source = new CustomAudioSource(); -AudioTrack senderTrack = factory.createAudioTrack("audio0", source); -peerConnection.addTrack(senderTrack, Collections.singletonList("stream0")); - -// Push PCM frames into the CustomAudioSource (10 ms chunks work well) -byte[] pcm = new byte[480 /* frames */ * 2 /* ch */ * 2 /* bytes */]; -source.pushAudio(pcm, 16, 48000, 2, 480); - -// ... later, stop -adm.stopRecording(); -adm.dispose(); -factory.dispose(); -``` - -::: info -- Initialization order matters: call `initRecording()` before `startRecording()`. -- The module exposes one virtual recording device; selection calls succeed with index 0. -- Stereo can be enabled/disabled via the standard ADM methods; by default 1 channel is used. -- If no AudioTransport is registered (no source), silence is injected to keep timings consistent. -::: - -## When to use HeadlessAudioDeviceModule vs. dummy audio layer on AudioDeviceModule - -- Prefer `HeadlessAudioDeviceModule` when you need to receive remote audio frames in a headless environment and consume them via `AudioTrack.addSink(AudioSink)`, or when you need to send audio from a custom source without touching physical devices. The headless module drives both playout and recording pipelines while no real system audio device is opened. -- Using a standard `AudioDeviceModule` with `AudioLayer.kDummyAudio` disables actual audio I/O; the audio pipeline is not started for playout and sinks will typically not receive audio frame callbacks. Use this only when you intentionally do not want any audio delivery (e.g., video‑only or fully custom audio). - -Related guides: -- [Audio Device Selection](/guide/audio/audio-devices) -- [Custom Audio Source](/guide/audio/custom-audio-source) - -## Limitations and notes -- No real audio is played or captured; playout frames are pulled from the render pipeline and discarded, and capture frames are pulled from your source (or zeroed) and delivered into WebRTC. -- Always follow the lifecycles: `initPlayout()` before `startPlayout()`, and `initRecording()` before `startRecording()`. Stop before dispose. -- The library handles native loading internally; instantiate and use the module as shown above. diff --git a/docs/guide/build.md b/docs/guide/build.md deleted file mode 100644 index a1da500..0000000 --- a/docs/guide/build.md +++ /dev/null @@ -1,31 +0,0 @@ -# Build Notes - -To build the native code, be sure to install the prerequisite software (follow the links): - -**Note**: You don't have to install the Depot Tools, the build script will do that for you. - -| OS | Build Instructions | -| --------- | ----------------------------------------------------------------- | -| Linux | [Ubuntu][build-linux-ubuntu], [other distros][build-linux-other] | -| macOS | Xcode 9 or higher | -| Windows | [Visual Studio][build-windows] | - -Assuming you have all the prerequisites installed for your OS, run: - -```shell -mvn install -``` - -On the first run, the WebRTC source tree will be loaded into the `//webrtc` directory. This will take a while and require about 20 GB of disk space. - -## Build Parameters - -| Parameter | Description | Default Value | -| ------------------ | ------------------------------------------------------ |-----------------------------| -| webrtc.branch | The WebRTC branch to checkout. | branch-heads/7339 | -| webrtc.src.dir | The absolute checkout path for the WebRTC source tree. | /\/webrtc | -| webrtc.install.dir | The install path for the compiled WebRTC library. Is also used to link against a pre-compiled WebRTC library to reduce build time. | /\/webrtc/build | - -[build-linux-ubuntu]: https://chromium.googlesource.com/chromium/src/+/master/docs/linux/build_instructions.md#system-requirements -[build-linux-other]: https://chromium.googlesource.com/chromium/src/+/master/docs/linux/build_instructions.md#Notes-for-other-distros -[build-windows]: https://chromium.googlesource.com/chromium/src/+/master/docs/windows_build_instructions.md#visual-studio \ No newline at end of file diff --git a/docs/guide/data/data-channels.md b/docs/guide/data/data-channels.md deleted file mode 100644 index e11e8eb..0000000 --- a/docs/guide/data/data-channels.md +++ /dev/null @@ -1,304 +0,0 @@ -# Data Channels - -This guide explains how to use WebRTC data channels with the webrtc-java library. Data channels provide a bidirectional communication mechanism that can be used to send arbitrary data between peers. - -## Overview - -WebRTC data channels allow you to: -- Send and receive text or binary data between peers -- Configure reliability and ordering properties -- Set up multiple channels with different configurations -- Monitor channel state changes and buffer amounts - -Data channels are created through an `RTCPeerConnection` and use the SCTP protocol for data transmission. - -## Creating a Data Channel - -To create a data channel, you need an established `RTCPeerConnection`. You can then call the `createDataChannel` method with a label and optional configuration: - -```java -import dev.onvoid.webrtc.RTCPeerConnection; -import dev.onvoid.webrtc.RTCDataChannel; -import dev.onvoid.webrtc.RTCDataChannelInit; - -// Assuming you already have a PeerConnectionFactory and RTCConfiguration -RTCPeerConnection peerConnection = factory.createPeerConnection(config, peerConnectionObserver); - -// Create a data channel with default configuration -RTCDataChannel dataChannel = peerConnection.createDataChannel("myChannel", new RTCDataChannelInit()); -``` - -### Data Channel Configuration - -You can customize the behavior of a data channel by configuring the `RTCDataChannelInit` object: - -```java -RTCDataChannelInit config = new RTCDataChannelInit(); - -// Configure ordering (default: true) -config.ordered = true; // Messages will be delivered in order - -// Configure reliability -// Option 1: Reliable (default) -config.maxPacketLifeTime = -1; -config.maxRetransmits = -1; - -// Option 2: Time-limited reliability -config.maxPacketLifeTime = 1000; // Retransmit for up to 1000ms -config.maxRetransmits = -1; // Don't use retransmit count limit - -// Option 3: Count-limited reliability -config.maxPacketLifeTime = -1; // Don't use time limit -config.maxRetransmits = 5; // Retransmit up to 5 times - -// Note: You cannot set both maxPacketLifeTime and maxRetransmits - -// Configure channel negotiation (default: false) -config.negotiated = false; // Channel will be announced in-band - -// Configure channel ID (default: -1, auto-assigned) -config.id = -1; // Let WebRTC assign an ID - -// Configure sub-protocol (default: null) -config.protocol = "my-protocol"; // Optional sub-protocol name - -// Configure priority (default: LOW) -config.priority = RTCPriorityType.LOW; - -// Create the data channel with this configuration -RTCDataChannel dataChannel = peerConnection.createDataChannel("myChannel", config); -``` - -## Handling Data Channel Events - -To receive events from a data channel, you need to implement the `RTCDataChannelObserver` interface and register it with the data channel: - -```java -import dev.onvoid.webrtc.RTCDataChannelObserver; -import dev.onvoid.webrtc.RTCDataChannelBuffer; -import dev.onvoid.webrtc.RTCDataChannelState; - -dataChannel.registerObserver(new RTCDataChannelObserver() { - @Override - public void onBufferedAmountChange(long previousAmount) { - // Called when the buffered amount changes - long currentAmount = dataChannel.getBufferedAmount(); - System.out.println("Buffered amount changed from " + previousAmount + - " to " + currentAmount + " bytes"); - } - - @Override - public void onStateChange() { - // Called when the data channel state changes - RTCDataChannelState state = dataChannel.getState(); - System.out.println("Data channel state changed to: " + state); - - // Handle different states - switch (state) { - case CONNECTING: - System.out.println("Data channel is being established"); - break; - case OPEN: - System.out.println("Data channel is open and ready to use"); - break; - case CLOSING: - System.out.println("Data channel is being closed"); - break; - case CLOSED: - System.out.println("Data channel is closed"); - break; - } - } - - @Override - public void onMessage(RTCDataChannelBuffer buffer) { - // Called when a message is received - // IMPORTANT: The buffer data will be freed after this method returns, - // so you must copy it if you need to use it asynchronously - - if (buffer.binary) { - // Handle binary data - handleBinaryMessage(buffer.data); - } else { - // Handle text data - handleTextMessage(buffer.data); - } - } -}); -``` - -### Receiving Data Channels - -When the remote peer creates a data channel, the `onDataChannel` method of your `PeerConnectionObserver` will be called: - -```java -import dev.onvoid.webrtc.PeerConnectionObserver; - -public class MyPeerConnectionObserver implements PeerConnectionObserver { - // Other PeerConnectionObserver methods... - - @Override - public void onDataChannel(RTCDataChannel dataChannel) { - System.out.println("Received data channel: " + dataChannel.getLabel()); - - // Register an observer to handle events from this channel - dataChannel.registerObserver(new MyDataChannelObserver()); - } -} -``` - -## Sending and Receiving Data - -### Sending Data - -You can send text or binary data through a data channel using the `send` method: - -```java -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; - -// Send text data -String textMessage = "Hello, WebRTC!"; -ByteBuffer textBuffer = ByteBuffer.wrap(textMessage.getBytes(StandardCharsets.UTF_8)); -RTCDataChannelBuffer textChannelBuffer = new RTCDataChannelBuffer(textBuffer, false); - -try { - dataChannel.send(textChannelBuffer); -} catch (Exception e) { - System.err.println("Failed to send text message: " + e.getMessage()); -} - -// Send binary data -byte[] binaryData = new byte[] { 0x01, 0x02, 0x03, 0x04 }; -ByteBuffer binaryBuffer = ByteBuffer.wrap(binaryData); -RTCDataChannelBuffer binaryChannelBuffer = new RTCDataChannelBuffer(binaryBuffer, true); - -try { - dataChannel.send(binaryChannelBuffer); -} catch (Exception e) { - System.err.println("Failed to send binary data: " + e.getMessage()); -} -``` - -### Receiving Data - -To receive data, implement the `onMessage` method in your `RTCDataChannelObserver`: - -```java -@Override -public void onMessage(RTCDataChannelBuffer buffer) { - ByteBuffer data = buffer.data; - - if (buffer.binary) { - // Handle binary data - byte[] binaryData; - - if (data.hasArray()) { - binaryData = data.array(); - } else { - binaryData = new byte[data.remaining()]; - data.get(binaryData); - } - - System.out.println("Received binary data, " + binaryData.length + " bytes"); - // Process binary data... - } else { - // Handle text data - byte[] textBytes; - - if (data.hasArray()) { - textBytes = data.array(); - } else { - textBytes = new byte[data.remaining()]; - data.get(textBytes); - } - - String text = new String(textBytes, StandardCharsets.UTF_8); - System.out.println("Received text message: " + text); - // Process text message... - } -} -``` - -## Data Channel Properties - -You can query various properties of a data channel: - -```java -// Get the channel label -String label = dataChannel.getLabel(); - -// Check if the channel is reliable -boolean reliable = dataChannel.isReliable(); - -// Check if messages are delivered in order -boolean ordered = dataChannel.isOrdered(); - -// Get the maximum packet lifetime (in milliseconds) -int maxPacketLifeTime = dataChannel.getMaxPacketLifeTime(); - -// Get the maximum number of retransmits -int maxRetransmits = dataChannel.getMaxRetransmits(); - -// Get the sub-protocol -String protocol = dataChannel.getProtocol(); - -// Check if the channel was negotiated by the application -boolean negotiated = dataChannel.isNegotiated(); - -// Get the channel ID -int id = dataChannel.getId(); - -// Get the current state -RTCDataChannelState state = dataChannel.getState(); - -// Get the amount of buffered data (in bytes) -long bufferedAmount = dataChannel.getBufferedAmount(); -``` - -## Closing and Cleanup - -When you're done with a data channel, you should properly clean it up: - -```java -// Unregister the observer -dataChannel.unregisterObserver(); - -// Close the data channel -dataChannel.close(); - -// Dispose of native resources -dataChannel.dispose(); -``` - -## Best Practices - -1. **Error Handling**: Always wrap `send` calls in try-catch blocks as they can throw exceptions if the buffer is full or the channel is not in the `OPEN` state. - -2. **Buffer Management**: Monitor the buffered amount to avoid overwhelming the channel. If `getBufferedAmount()` returns a large value, consider pausing sending until it decreases. - -3. **Copy Received Data**: Remember that the data in the `RTCDataChannelBuffer` will be freed after the `onMessage` method returns. If you need to process the data asynchronously, make a copy of it. - -4. **Proper Cleanup**: Always unregister observers, close channels, and dispose of native resources to prevent memory leaks. - -5. **State Checking**: Check the channel state before sending data to avoid exceptions: - ```java - if (dataChannel.getState() == RTCDataChannelState.OPEN) { - // Safe to send data - } - ``` - -6. **Multiple Channels**: Consider using multiple data channels with different configurations for different types of data (e.g., one reliable channel for critical data and one unreliable channel for real-time updates). - -7. **Binary vs. Text**: Use the appropriate flag when creating `RTCDataChannelBuffer` objects: - - `false` for UTF-8 text data - - `true` for binary data - -## Conclusion - -WebRTC data channels provide a powerful way to establish peer-to-peer communication for transferring arbitrary data between clients. -Data channels complement WebRTC's audio and video capabilities, making it possible to build comprehensive real-time applications that include text chat, file transfers, game state synchronization, and other custom data exchange requirements. - -For optimal performance, remember to follow the best practices outlined in this guide, particularly regarding buffer management and proper cleanup of resources. - -For more information on other WebRTC features, refer to the additional guides in the documentation. \ No newline at end of file diff --git a/docs/guide/examples.md b/docs/guide/examples.md deleted file mode 100644 index 86ee625..0000000 --- a/docs/guide/examples.md +++ /dev/null @@ -1,97 +0,0 @@ -# Examples - -This section provides an overview of the example applications included in the `webrtc-examples` Maven module. These examples demonstrate various features and capabilities of the webrtc-java library. - -## PeerConnection - -The [`PeerConnectionExample`](https://github.com/devopvoid/webrtc-java/blob/master/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/PeerConnectionExample.java) demonstrates how to set up a peer connection with audio and video tracks to be able to send and receive media. - -**Key features demonstrated:** -- Creating a `PeerConnectionFactory` -- Creating audio and video tracks -- Setting up a peer connection -- Adding tracks to the peer connection for sending media -- Implementing callbacks to receive incoming audio and video frames - -This example provides a foundation for building WebRTC applications that need to handle audio and video communication. - -## WHEP - -The [`WhepExample`](https://github.com/devopvoid/webrtc-java/blob/master/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/WhepExample.java) demonstrates an implementation of WebRTC HTTP Egress Protocol (WHEP) client, which is a standardized protocol for WebRTC ingestion. - -**Key features demonstrated:** -- Setting up a WebRTC peer connection -- Creating and sending an SDP offer to a WHEP endpoint -- Receiving and processing an SDP answer -- Establishing media streaming over WebRTC - -This example is useful for applications that need to receive media streams from WHEP-compatible servers, such as live streaming platforms. - -## Codec List - -The [`CodecListExample`](https://github.com/devopvoid/webrtc-java/blob/master/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/CodecListExample.java) demonstrates how to list all supported codecs with the WebRTC peer-connection-factory. - -**Key features demonstrated:** -- Creating a `PeerConnectionFactory` -- Getting the supported codecs for both sending and receiving audio and video -- Displaying detailed information about each codec - -This example is useful for understanding what codecs are available on the current system, which can help with debugging compatibility issues or optimizing media quality. - -## Desktop Video - -The [`DesktopVideoExample`](https://github.com/devopvoid/webrtc-java/blob/master/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/DesktopVideoExample.java) demonstrates how to set up a peer connection with a desktop video source for screen or window capture. - -**Key features demonstrated:** -- Creating a `PeerConnectionFactory` -- Getting available desktop sources (screens and windows) -- Creating a `VideoDesktopSource` for capturing screen or window content -- Configuring the `VideoDesktopSource` properties -- Creating a video track with the desktop source -- Setting up a peer connection - -This example is particularly useful for applications that need to implement screen sharing or remote desktop functionality. - -## Web Client - -The [`WebClientExample`](https://github.com/devopvoid/webrtc-java/blob/master/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/WebClientExample.java) demonstrates how to combine WebSocket signaling with WebRTC peer connections for real-time communication between web and Java clients. - -**Key features demonstrated:** -- Connecting to a signaling server using WebSockets -- Setting up audio and video media tracks -- Creating and managing WebRTC peer connections -- Handling signaling messages (offers, answers, ICE candidates) -- Joining and leaving rooms for multi-user communication -- Using custom audio sources for audio streaming - -This example is valuable for applications that need to establish WebRTC connections between Java clients and web browsers, enabling cross-platform real-time communication with audio and video. - -::: info -Before running the `WebClientExample`, you need to start the `WebServer` first. The `WebServer` provides the signaling service required for WebRTC connection establishment: -::: - -```bash -mvn exec:java -D"exec.mainClass=dev.onvoid.webrtc.examples.web.server.WebServer" -``` - -And the browser client is reachable at this url: `https://localhost:8443` - - -## Running the Examples - -To run these examples, you need to navigate into the directory `webrtc-java/webrtc-example` in the project. -You can then execute the main method of each example class. - -For example, to run the `CodecListExample`: - -```bash -mvn exec:java -D"exec.mainClass=dev.onvoid.webrtc.examples.CodecListExample" -``` - -Or to run the `WebClientExample`: - -```bash -mvn exec:java -D"exec.mainClass=dev.onvoid.webrtc.examples.web.WebClientExample" -``` - -Note that these examples focus on setting up the local components for WebRTC communication. In a real application, you would need to establish a connection with a remote peer through a signaling channel (e.g., WebSocket). The `WebClientExample` demonstrates this by connecting to a signaling server. \ No newline at end of file diff --git a/docs/guide/get-started.md b/docs/guide/get-started.md deleted file mode 100644 index 2fb828a..0000000 --- a/docs/guide/get-started.md +++ /dev/null @@ -1,306 +0,0 @@ -# Get Started - -This guide will help you get started with webrtc-java quickly. We'll cover installation, basic setup, and simple examples to demonstrate core functionality. - -## Supported Platforms -Maven Central artifacts contain native libraries that can be loaded on the following platforms: - -| | x64 | arm | arm64 | -|-----------|---------|---------|---------| -| Linux | ✔ | ✔ | ✔ | -| macOS | ✔ | - | ✔ | -| Windows | ✔ | - | - | - - -## Installation - -### Maven - -Add the following dependency to your `pom.xml`: - -```xml - - dev.onvoid.webrtc - webrtc-java - {{ VERSION }} - -``` - -::: info -**Native library classifiers** - -The webrtc-java artifact will automatically add the dependency for the native library artifact matching the currently running operating system and architecture at runtime. - -If you encounter issues loading the native library "webrtc-java", you can declare the platform-specific classifier explicitly. For example, for Windows 64-Bit: - -```xml - - dev.onvoid.webrtc - webrtc-java - {{ VERSION }} - windows-x86_64 - -``` - -Complete list of available classifiers: -- windows-x86_64 -- macos-x86_64 -- macos-aarch64 -- linux-x86_64 -- linux-aarch64 -- linux-aarch32 -::: - -#### Using SNAPSHOT Versions - -If you want to use the latest development version, you can use a SNAPSHOT release: - -```xml - - dev.onvoid.webrtc - webrtc-java - {{ VERSION_SNAPSHOT }} - -``` - -To use SNAPSHOT versions, you need to add the following repository configuration to your `pom.xml`: - -```xml - - - Central Portal Snapshots - central-portal-snapshots - https://central.sonatype.com/repository/maven-snapshots/ - - false - - - true - - - -``` - -### Gradle - -Add the following to your `build.gradle`: - -```groovy -implementation "dev.onvoid.webrtc:webrtc-java:{{ VERSION }}" -``` - -For specific platforms, add the appropriate classifier: - -```groovy -implementation group: "dev.onvoid.webrtc", name: "webrtc-java", version: "{{ VERSION }}", classifier: "windows-x86_64" -implementation group: "dev.onvoid.webrtc", name: "webrtc-java", version: "{{ VERSION }}", classifier: "macos-x86_64" -implementation group: "dev.onvoid.webrtc", name: "webrtc-java", version: "{{ VERSION }}", classifier: "macos-aarch64" -implementation group: "dev.onvoid.webrtc", name: "webrtc-java", version: "{{ VERSION }}", classifier: "linux-x86_64" -implementation group: "dev.onvoid.webrtc", name: "webrtc-java", version: "{{ VERSION }}", classifier: "linux-aarch64" -implementation group: "dev.onvoid.webrtc", name: "webrtc-java", version: "{{ VERSION }}", classifier: "linux-aarch32" -``` - -## Basic Setup - -### Initialize the WebRTC Library - -First, create a `PeerConnectionFactory` which is the entry point for most WebRTC operations: - -```java -import dev.onvoid.webrtc.PeerConnectionFactory; - -// Create a peer connection factory -PeerConnectionFactory factory = new PeerConnectionFactory(); -``` - -### Create a Peer Connection - -To establish communication with another peer, you need to create a `RTCPeerConnection`: - -```java -import dev.onvoid.webrtc.RTCConfiguration; -import dev.onvoid.webrtc.RTCIceServer; -import dev.onvoid.webrtc.RTCPeerConnection; -import dev.onvoid.webrtc.PeerConnectionObserver; - -// Configure ICE servers (STUN/TURN) -RTCConfiguration config = new RTCConfiguration(); -RTCIceServer iceServer = new RTCIceServer(); -iceServer.urls.add("stun:stun.l.google.com:19302"); -config.iceServers.add(iceServer); - -// Create a peer connection with an observer to handle events -RTCPeerConnection peerConnection = factory.createPeerConnection(config, new PeerConnectionObserver() { - // Implement required methods -}); -``` - -## Signaling - -WebRTC requires a signaling mechanism to exchange connection information between peers. The library doesn't provide this, so you'll need to implement it using your preferred method (WebSockets, HTTP, etc.). - -Here's a simplified example of the signaling process: - -```java -// Create an offer -RTCOfferOptions options = new RTCOfferOptions(); - -peerConnection.createOffer(options, new CreateSessionDescriptionObserver() { - @Override - public void onSuccess(RTCSessionDescription description) { - // Set local description - peerConnection.setLocalDescription(description, new SetSessionDescriptionObserver() { - @Override - public void onSuccess() { - // Send the offer to the remote peer via your signaling channel - signalingChannel.send(description); - } - - @Override - public void onFailure(String error) { - System.err.println("Failed to set local description: " + error); - } - }); - } - - @Override - public void onFailure(String error) { - System.err.println("Failed to create offer: " + error); - } -}); - -// When you receive an answer from the remote peer via your signaling channel -signalingChannel.onMessage(message -> { - RTCSessionDescription remoteDescription = parseSessionDescription(message); - peerConnection.setRemoteDescription(remoteDescription, new SetSessionDescriptionObserver() { - @Override - public void onSuccess() { - System.out.println("Remote description set successfully"); - } - - @Override - public void onFailure(String error) { - System.err.println("Failed to set remote description: " + error); - } - }); -}); - -// Handle ICE candidates -PeerConnectionObserver connectionObserver = new PeerConnectionObserver() { - @Override - public void onIceCandidate(RTCIceCandidate candidate) { - // Send the ICE candidate to the remote peer via your signaling channel - signalingChannel.send(candidate); - } -}; - -// When you receive an ICE candidate from the remote peer -signalingChannel.onIceCandidate(candidateMessage -> { - RTCIceCandidate candidate = parseIceCandidate(candidateMessage); - peerConnection.addIceCandidate(candidate); -}); -``` - -## Media Streams - -### Accessing Media Devices - -To query media devices (cameras and microphones): - -```java -import dev.onvoid.webrtc.media.MediaDevices; -import dev.onvoid.webrtc.media.video.VideoDevice; -import dev.onvoid.webrtc.media.audio.AudioDevice; - -// Get available video devices -List videoDevices = MediaDevices.getVideoCaptureDevices(); -for (VideoDevice device : videoDevices) { - System.out.println("Video device: " + device.getName()); -} - -// Get available audio devices -List audioDevices = MediaDevices.getAudioCaptureDevices(); -for (AudioDevice device : audioDevices) { - System.out.println("Audio device: " + device.getName()); -} -``` - -### Creating Media Tracks - -To create audio and video tracks: - -```java -import dev.onvoid.webrtc.media.video.VideoTrack; -import dev.onvoid.webrtc.media.audio.AudioTrack; -import dev.onvoid.webrtc.media.video.VideoDeviceSource; -import dev.onvoid.webrtc.media.audio.AudioDeviceSource; - -// Create a video source and track -VideoDeviceSource videoSource = new VideoDeviceSource(); -videoSource.setVideoCaptureDevice(videoDevices.get(0)); // Use the first available camera -VideoTrack videoTrack = factory.createVideoTrack("video0", videoSource); - -// Create an audio source and track -AudioOptions audioOptions = new AudioOptions(); -audioOptions.echoCancellation = true; -audioOptions.autoGainControl = true; -audioOptions.noiseSuppression = true; - -// Create an audio source using the default audio device -AudioTrackSource audioSource = factory.createAudioSource(audioOptions); -AudioTrack audioTrack = factory.createAudioTrack("audio0", audioSource); -``` - -::: info -Audio devices can be specified via the `AudioDeviceModule`, see the guide on [Audio Devices][audio-devices] for more details. -::: - -### Adding Tracks to Peer Connection - -```java -import java.util.ArrayList; -import java.util.List; - -// Add tracks to the peer connection -List streamIds = new ArrayList<>(); -streamIds.add("stream1"); -peerConnection.addTrack(videoTrack, streamIds); -peerConnection.addTrack(audioTrack, streamIds); -``` - -## Cleanup - -Always properly dispose of resources when you're done: - -```java -// Dispose of tracks -videoTrack.dispose(); -audioTrack.dispose(); - -// Dispose of sources -videoSource.dispose(); - -// Close peer connection and release resources -peerConnection.close(); - -// Dispose of factory -factory.dispose(); -``` - -## Next Steps - -Now that you have a basic understanding of webrtc-java, you can explore more advanced features: - -- [Data Channels][data-channels] - Learn more about data channels -- [RTC Stats][rtc-stats] - Monitor connection quality -- [Desktop Capture][desktop-capture] - Share screens and windows -- [All Guides][overview] - Complete list of guides - -For a complete API reference, check the [JavaDoc][javadoc]. - -[audio-devices]: /guide/audio/audio-devices -[data-channels]: /guide/data/data-channels -[rtc-stats]: /guide/monitoring/rtc-stats -[desktop-capture]: /guide/video/desktop-capture -[overview]: /guide/ -[javadoc]: https://javadoc.io/doc/dev.onvoid.webrtc/webrtc-java/latest/index.html \ No newline at end of file diff --git a/docs/guide/index.md b/docs/guide/index.md deleted file mode 100644 index 6e1b913..0000000 --- a/docs/guide/index.md +++ /dev/null @@ -1,40 +0,0 @@ -# Guide Overview - -This section provides detailed guides for various features of the webrtc-java library. - -## Media Basics - -- [Media Devices](/guide/media/media-devices) - Working with audio and video devices -- [Bitrate and Framerate Constraints](/guide/media/constraints) - Controlling media quality -- [Send-only and Receive-only](/guide/media/directionality) - Configure transceiver directions (send-only, receive-only or inactive) - -## Audio - -- [Audio Device Selection](/guide/audio/audio-devices) - Selecting and configuring audio devices -- [Audio Processing](/guide/audio/audio-processing) - Voice processing components -- [Custom Audio Source](/guide/audio/custom-audio-source) - Using custom audio sources with WebRTC -- [Headless Audio](/guide/audio/headless-audio) - Playout pull without touching real OS audio devices -- [DTMF Sender](/guide/audio/dtmf-sender) - Sending DTMF tones in a call - -## Video - -- [Camera Capture](/guide/video/camera-capture) - Capturing video from cameras -- [Desktop Capture](/guide/video/desktop-capture) - Capturing and sharing screens and windows -- [Custom Video Source](/guide/video/custom-video-source) - Using custom video sources with WebRTC - -## Data Communication - -- [Data Channels](/guide/data/data-channels) - Sending and receiving arbitrary data between peers - -## Networking and ICE - -- [Port Allocator Config](/guide/networking/port-allocator-config) - Restrict ICE port ranges and control candidate gathering behavior - -## Monitoring and Debugging - -- [RTC Stats](/guide/monitoring/rtc-stats) - Monitoring connection quality and performance -- [Logging](/guide/monitoring/logging) - Configuring and using the logging system - -## Additional Resources - -For a complete API reference, check the [JavaDoc](https://javadoc.io/doc/dev.onvoid.webrtc/webrtc-java/latest/index.html). \ No newline at end of file diff --git a/docs/guide/introduction.md b/docs/guide/introduction.md deleted file mode 100644 index 1065968..0000000 --- a/docs/guide/introduction.md +++ /dev/null @@ -1,24 +0,0 @@ -# Introduction - -webrtc-java is a Java wrapper for the [WebRTC Native API](https://webrtc.github.io/webrtc-org/native-code/native-apis), providing similar functionality to the [W3C JavaScript API](https://w3c.github.io/webrtc-pc). It allows Java developers to build real-time communication applications for desktop platforms without having to work directly with native code. - -The library provides a comprehensive set of Java classes that map to the WebRTC C++ API, making it possible to establish peer-to-peer connections, transmit audio and video, share screens, and exchange arbitrary data between applications. - -## Overview - -For more detailed information, check out the documentation: - -- [Get Started](/guide/get-started) - Get up and running quickly with webrtc-java -- [Guides](/guide/) - Comprehensive documentation on using the library -- [Examples](/guide/examples) - Sample code demonstrating various features -- [Build Notes](/guide/build) - Instructions for building the library from source - -## License - -Copyright (c) 2019 Alex Andres - -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - -[http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0) - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. \ No newline at end of file diff --git a/docs/guide/media/constraints.md b/docs/guide/media/constraints.md deleted file mode 100644 index fb3b32e..0000000 --- a/docs/guide/media/constraints.md +++ /dev/null @@ -1,127 +0,0 @@ -# Media Constraints - -This guide explains how to set bitrate and framerate constraints for MediaStreamTrack of RTCRtpSender. It covers: - -- Understanding RTCRtpSender Parameters -- Setting maximum and minimum bitrate constraints -- Setting maximum framerate constraints -- Scaling video resolution - -## Understanding RTCRtpSender Parameters - -The `RTCRtpSender` class allows you to control how a `MediaStreamTrack` is encoded and transmitted to a remote peer. You can modify encoding parameters such as bitrate and framerate by getting the current parameters, modifying them, and then setting the updated parameters. - -The key methods for this process are: - -- `getParameters()` - Returns the current parameters for how the track is encoded and transmitted -- `setParameters(RTCRtpSendParameters parameters)` - Updates how the track is encoded and transmitted - -It's important to note that you must first call `getParameters()`, modify the returned object, and then call `setParameters()` with the modified object. This is because the parameters object contains a transaction ID that ensures there are no intervening changes. - -## Setting Bitrate Constraints - -You can set both maximum and minimum bitrate constraints for a MediaStreamTrack. These constraints help control the quality and bandwidth usage of the transmitted media. - -```java -// Import required classes -import dev.onvoid.webrtc.RTCRtpSender; -import dev.onvoid.webrtc.RTCRtpSendParameters; -import dev.onvoid.webrtc.RTCRtpEncodingParameters; - -// Assuming you have an RTCRtpSender instance -RTCRtpSender sender = /* ... */; - -// Get the current parameters -RTCRtpSendParameters parameters = sender.getParameters(); - -// Check if there are any encodings -if (parameters.encodings != null && !parameters.encodings.isEmpty()) { - // Set maximum bitrate (in bits per second) - // For example, 1,000,000 bps = 1 Mbps - parameters.encodings.get(0).maxBitrate = 1000000; - - // Set minimum bitrate (in bits per second) - // For example, 100,000 bps = 100 Kbps - parameters.encodings.get(0).minBitrate = 100000; - - // Apply the modified parameters - sender.setParameters(parameters); -} -``` - -Setting a maximum bitrate helps ensure that your application doesn't use excessive bandwidth, which is particularly important for users with limited data plans or slower connections. Setting a minimum bitrate can help maintain a certain level of quality, though it may cause issues if the available bandwidth falls below this threshold. - -## Setting Framerate Constraints - -You can also set a maximum framerate constraint for video tracks. This can be useful for limiting CPU usage or bandwidth consumption. - -```java -// Import required classes -import dev.onvoid.webrtc.RTCRtpSender; -import dev.onvoid.webrtc.RTCRtpSendParameters; -import dev.onvoid.webrtc.RTCRtpEncodingParameters; - -// Assuming you have an RTCRtpSender instance with a video track -RTCRtpSender sender = /* ... */; - -// Get the current parameters -RTCRtpSendParameters parameters = sender.getParameters(); - -// Check if there are any encodings -if (parameters.encodings != null && !parameters.encodings.isEmpty()) { - // Set maximum framerate (in frames per second) - // For example, 15.0 fps - parameters.encodings.get(0).maxFramerate = 15.0; - - // Apply the modified parameters - sender.setParameters(parameters); -} -``` - -Setting a lower framerate can significantly reduce bandwidth usage, which is beneficial for users with limited bandwidth. However, it may result in less smooth video playback. - -## Scaling Video Resolution - -In addition to bitrate and framerate constraints, you can also scale down the resolution of a video track. This is done using the `scaleResolutionDownBy` parameter. - -```java -// Import required classes -import dev.onvoid.webrtc.RTCRtpSender; -import dev.onvoid.webrtc.RTCRtpSendParameters; -import dev.onvoid.webrtc.RTCRtpEncodingParameters; - -// Assuming you have an RTCRtpSender instance with a video track -RTCRtpSender sender = /* ... */; - -// Get the current parameters -RTCRtpSendParameters parameters = sender.getParameters(); - -// Check if there are any encodings -if (parameters.encodings != null && !parameters.encodings.isEmpty()) { - // Scale down resolution by a factor of 2 (each dimension) - // This will reduce the video size to 1/4 of the original - parameters.encodings.get(0).scaleResolutionDownBy = 2.0; - - // Apply the modified parameters - sender.setParameters(parameters); -} -``` - -The `scaleResolutionDownBy` parameter specifies how much to scale down the video in each dimension. For example, a value of 2.0 means the video will be scaled down by a factor of 2 in both width and height, resulting in a video that is 1/4 the size of the original. - -::: info -Note that these constraints are applied without requiring SDP renegotiation, making them suitable for dynamic adaptation to changing network conditions. -::: - -## Conclusion - -In this guide, we've explored several important techniques for controlling media quality and bandwidth usage in WebRTC applications. -These constraints provide powerful tools for adapting media quality dynamically in response to changing network conditions or device capabilities. -By implementing these techniques, you can: - -- Improve user experience on limited bandwidth connections -- Reduce data consumption for users with data caps -- Optimize performance on lower-powered devices -- Ensure more consistent connection quality across various network conditions - -You can use this code as a starting point for your own applications that need to control media quality and bandwidth usage. \ No newline at end of file diff --git a/docs/guide/media/directionality.md b/docs/guide/media/directionality.md deleted file mode 100644 index e6e73c2..0000000 --- a/docs/guide/media/directionality.md +++ /dev/null @@ -1,143 +0,0 @@ -# Media Directionality - -This guide explains how to configure WebRTC media to be receive-only or send-only using the webrtc-java API. It also shows the equivalent configuration on the JavaScript (browser) side. You will learn how to: - -- Create receive-only audio/video transceivers -- Create send-only audio/video transceivers -- Change direction at runtime -- Understand the underlying SDP attributes (a=sendonly / a=recvonly / a=inactive) - -The examples build upon the RTCRtpTransceiver API, which is the recommended way to control directionality in modern WebRTC. - -Related API: -- `dev.onvoid.webrtc.RTCRtpTransceiver` -- `dev.onvoid.webrtc.RTCRtpTransceiverInit` -- `dev.onvoid.webrtc.RTCRtpTransceiverDirection` - -References in the repository: -- Tests: [RTCPeerConnectionTests.java](https://github.com/devopvoid/webrtc-java/blob/main/webrtc/src/test/java/dev/onvoid/webrtc/RTCPeerConnectionTests.java) -- Example (receive-only with WHEP): [WhepExample.java](https://github.com/devopvoid/webrtc-java/blob/main/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/WhepExample.java) - -## Concepts overview - -- `SEND_RECV`: Both sending and receiving are active (default when you add a track). -- `SEND_ONLY`: Only sending is negotiated; you won’t receive media on this transceiver. -- `RECV_ONLY`: Only receiving is negotiated; you won’t send media on this transceiver. -- `INACTIVE`: Neither sending nor receiving on this transceiver. - -These map to the SDP attributes a=sendrecv, a=sendonly, a=recvonly, a=inactive. - -## Receive-only example - -Use a transceiver with direction `RECV_ONLY` to indicate that you only want to receive media for a given kind (audio or video). You can optionally pass a dummy local track or omit sending entirely by not attaching a sending track. - -```java -import dev.onvoid.webrtc.*; -import dev.onvoid.webrtc.media.video.VideoDeviceSource; -import dev.onvoid.webrtc.media.video.VideoTrack; - -PeerConnectionFactory factory = new PeerConnectionFactory(); -RTCConfiguration config = new RTCConfiguration(); -RTCPeerConnection pc = factory.createPeerConnection(config, candidate -> {}); - -// Create a video track/source (can be a dummy source when only receiving) -VideoDeviceSource videoSource = new VideoDeviceSource(); -VideoTrack videoTrack = factory.createVideoTrack("videoTrack", videoSource); - -// Configure transceiver as RECV_ONLY -RTCRtpTransceiverInit init = new RTCRtpTransceiverInit(); -init.direction = RTCRtpTransceiverDirection.RECV_ONLY; -RTCRtpTransceiver transceiver = pc.addTransceiver(videoTrack, init); - -// Access the receiving track and attach a sink -MediaStreamTrack track = transceiver.getReceiver().getTrack(); -if (track instanceof dev.onvoid.webrtc.media.video.VideoTrack vTrack) { - vTrack.addSink(frame -> { - // Handle incoming frames - System.out.println("Received frame: " + frame); - frame.release(); - }); -} -``` - -::: info -- This pattern is used in the WhepExample included in the repository. -- When you create the offer, the SDP will contain a=recvonly for that m= section. -::: - -## Send-only example - -To send-only, set the transceiver direction to SEND_ONLY and provide a local track to send. - -```java -import dev.onvoid.webrtc.*; -import dev.onvoid.webrtc.media.audio.AudioOptions; -import dev.onvoid.webrtc.media.audio.AudioTrack; -import dev.onvoid.webrtc.media.audio.AudioTrackSource; - -PeerConnectionFactory factory = new PeerConnectionFactory(); -RTCPeerConnection pc = factory.createPeerConnection(new RTCConfiguration(), candidate -> {}); - -// Create an audio track to send -AudioTrackSource audioSource = factory.createAudioSource(new AudioOptions()); -AudioTrack audioTrack = factory.createAudioTrack("audioTrack", audioSource); - -// Configure transceiver as SEND_ONLY -RTCRtpTransceiverInit init = new RTCRtpTransceiverInit(); -init.direction = RTCRtpTransceiverDirection.SEND_ONLY; -RTCRtpTransceiver transceiver = pc.addTransceiver(audioTrack, init); - -// Optionally verify -assert transceiver.getDirection() == RTCRtpTransceiverDirection.SEND_ONLY; -``` - -When you create the offer with this setup, the SDP will include a=sendonly for the audio m= section. - -## Changing direction at runtime - -You can change the direction dynamically. Remember that direction changes typically require renegotiation (createOffer/setLocalDescription -> signal -> setRemoteDescription). - -```java -RTCRtpTransceiver transceiver = /* previously created */; - -// Change to INACTIVE -transceiver.setDirection(RTCRtpTransceiverDirection.INACTIVE); - -// Later switch to SEND_RECV -transceiver.setDirection(RTCRtpTransceiverDirection.SEND_RECV); - -// After changing directions, create a new offer and perform negotiation. -RTCOfferOptions opts = new RTCOfferOptions(); -pc.createOffer(opts, new CreateSessionDescriptionObserver() { - @Override - public void onSuccess(RTCSessionDescription description) { - pc.setLocalDescription(description, /* observer */ null); - // Send to remote and await/set remote answer accordingly - } - @Override - public void onFailure(String error) { /* handle error */ } -}); -``` - -::: tip -You can also control sending without renegotiation by replacing the sender’s track or disabling it via `MediaStreamTrack.setEnabled(false)`. However, the negotiated direction in SDP remains the same until you renegotiate. -::: - -## Common patterns and tips - -- If you only need to receive a stream from a server (e.g., WHEP), use `RECV_ONLY` and avoid capturing local devices. This simplifies permissions and reduces CPU usage. -- To temporarily stop sending without renegotiation, you can disable the sender’s track: `sender.getTrack().setEnabled(false)`. -- Use `INACTIVE` when neither sending nor receiving should occur on a transceiver, but you want to keep it for future use. -- Direction changes typically require a new offer/answer exchange. - -## Troubleshooting - -- No remote media arriving in `RECV_ONLY` mode: - - Ensure the remote endpoint actually sends media on that m= section. - - Verify codecs overlap (see `CodecListExample` in examples). - - Check network/firewall and ICE connectivity. -- Permissions prompts appear even in receive-only mode: - - Avoid creating real capture devices if you don’t need to send. You can add a transceiver with a dummy track. -- SDP direction not as expected: - - Confirm the transceiver direction before creating the offer. - - Some changes only apply after renegotiation. diff --git a/docs/guide/media/media-devices.md b/docs/guide/media/media-devices.md deleted file mode 100644 index ae3613d..0000000 --- a/docs/guide/media/media-devices.md +++ /dev/null @@ -1,182 +0,0 @@ -# Media Devices - -This guide explains how to work with media devices (microphones, speakers, and cameras). It covers: - -- Querying available media devices -- Getting device capabilities -- Listening for device hotplug events - -Cameras and microphones play a key role in WebRTC. In a more complex application, you will most likely want to check all the connected cameras and microphones and select the appropriate device for the WebRTC session. These devices can be enumerated with the class `MediaDevices`. With `MediaDevices` you can also listen for device changes, whenever a device is connected or disconnected. - -## Querying Media Devices - -The `MediaDevices` class provides methods to query all available media devices connected to the system. - -::: info -Query devices on worker threads, not on UI or render threads. -::: - -### Audio Capture Devices (Microphones) - -To get a list of all available microphones: - -```java -// Import required classes -import dev.onvoid.webrtc.media.MediaDevices; -import dev.onvoid.webrtc.media.audio.AudioDevice; -import java.util.List; - -// Get all microphones -List microphones = MediaDevices.getAudioCaptureDevices(); - -// Print microphone details -for (AudioDevice microphone : microphones) { - System.out.println("Microphone: " + microphone.getName()); - System.out.println(" Descriptor: " + microphone.getDescriptor()); -} - -// Get the default microphone -AudioDevice defaultMicrophone = MediaDevices.getDefaultAudioCaptureDevice(); -if (defaultMicrophone != null) { - System.out.println("Default Microphone: " + defaultMicrophone.getName()); -} -``` - -### Audio Render Devices (Speakers) - -To get a list of all available speakers: - -```java -// Import required classes -import dev.onvoid.webrtc.media.MediaDevices; -import dev.onvoid.webrtc.media.audio.AudioDevice; -import java.util.List; - -// Get all speakers -List speakers = MediaDevices.getAudioRenderDevices(); - -// Print speaker details -for (AudioDevice speaker : speakers) { - System.out.println("Speaker: " + speaker.getName()); - System.out.println(" Descriptor: " + speaker.getDescriptor()); -} - -// Get the default speaker -AudioDevice defaultSpeaker = MediaDevices.getDefaultAudioRenderDevice(); -if (defaultSpeaker != null) { - System.out.println("Default Speaker: " + defaultSpeaker.getName()); -} -``` - -### Video Capture Devices (Cameras) - -To get a list of all available cameras: - -```java -// Import required classes -import dev.onvoid.webrtc.media.MediaDevices; -import dev.onvoid.webrtc.media.video.VideoDevice; -import java.util.List; - -// Get all cameras -List cameras = MediaDevices.getVideoCaptureDevices(); - -// Print camera details -for (VideoDevice camera : cameras) { - System.out.println("Camera: " + camera.getName()); - System.out.println(" Descriptor: " + camera.getDescriptor()); -} -``` - -## Camera Capabilities - -You can query the capabilities of a specific camera to determine the supported resolutions and frame rates: - -```java -// Import required classes -import dev.onvoid.webrtc.media.MediaDevices; -import dev.onvoid.webrtc.media.video.VideoDevice; -import dev.onvoid.webrtc.media.video.VideoCaptureCapability; -import java.util.List; - -// Get all cameras -List cameras = MediaDevices.getVideoCaptureDevices(); -if (cameras.isEmpty()) { - System.out.println("No cameras found"); - return; -} - -// Get the first camera -VideoDevice camera = cameras.get(0); -System.out.println("Camera: " + camera.getName()); - -// Get camera capabilities -List capabilities = MediaDevices.getVideoCaptureCapabilities(camera); - -// Print camera capabilities -for (VideoCaptureCapability capability : capabilities) { - System.out.println(" Resolution: " + capability.width + "x" + capability.height); - System.out.println(" Frame Rate: " + capability.frameRate + " fps"); -} -``` - -## Hotplug Events - -You can listen for device hotplug events to be notified when devices are connected or disconnected: - -```java -// Import required classes -import dev.onvoid.webrtc.media.Device; -import dev.onvoid.webrtc.media.DeviceChangeListener; -import dev.onvoid.webrtc.media.MediaDevices; -import dev.onvoid.webrtc.media.audio.AudioDevice; -import dev.onvoid.webrtc.media.video.VideoDevice; - -// Create a device change listener -DeviceChangeListener listener = new DeviceChangeListener() { - @Override - public void deviceConnected(Device device) { - System.out.println("Device connected: " + device.getName()); - - if (device instanceof AudioDevice) { - System.out.println(" Type: Audio Device"); - } - else if (device instanceof VideoDevice) { - System.out.println(" Type: Video Device"); - } - } - - @Override - public void deviceDisconnected(Device device) { - System.out.println("Device disconnected: " + device.getName()); - - if (device instanceof AudioDevice) { - System.out.println(" Type: Audio Device"); - } - else if (device instanceof VideoDevice) { - System.out.println(" Type: Video Device"); - } - } -}; - -// Register the listener -MediaDevices.addDeviceChangeListener(listener); - -// ... later, when you're done listening for events -// Unregister the listener -MediaDevices.removeDeviceChangeListener(listener); -``` - -## Conclusion - -This guide has provided a comprehensive overview of working with media devices in the WebRTC library. -When implementing media device handling in your applications, consider these best practices: - -- Always check if devices exist before trying to use them -- Handle the case where no devices are available gracefully -- Provide users with the ability to select from available devices -- Implement hotplug listeners to dynamically update available devices -- Remember to unregister device listeners when they're no longer needed -- Query devices on worker threads, not on UI or render threads. - -You can use the code examples in this guide as a starting point for applications that need to work with media devices in WebRTC scenarios like video conferencing, live streaming, or media recording. \ No newline at end of file diff --git a/docs/guide/monitoring/logging.md b/docs/guide/monitoring/logging.md deleted file mode 100644 index 24852d2..0000000 --- a/docs/guide/monitoring/logging.md +++ /dev/null @@ -1,135 +0,0 @@ -# Logging - -This guide explains how to use the logging capabilities. The library provides native WebRTC logging through the `dev.onvoid.webrtc.logging.Logging` class. - -## Native WebRTC Logging - -The `Logging` class provides access to the native WebRTC logging system, allowing you to: -- Log messages at different severity levels -- Configure logging behavior -- Implement custom log sinks to capture and process log messages - -### Severity Levels - -The `Logging` class defines the following severity levels (in order of increasing severity): - -| Level | Description | -|-------|-------------| -| `VERBOSE` | For data which should not appear in the normal debug log, but should appear in diagnostic logs | -| `INFO` | Used in debugging | -| `WARNING` | Something that may warrant investigation | -| `ERROR` | A critical error has occurred | -| `NONE` | Do not log | - -### Basic Logging - -The `Logging` class provides several methods for logging messages: - -```java -import dev.onvoid.webrtc.logging.Logging; - -// Log messages with different severity levels -Logging.verbose("Detailed information for diagnostic purposes"); -Logging.info("General information about application operation"); -Logging.warn("Potential issue that might need attention"); -Logging.error("Critical error that affects application operation"); - -// Log an error with exception details -try { - // Some operation that might throw an exception -} catch (Exception e) { - Logging.error("Failed to perform operation", e); -} -``` - -### Configuring Logging Behavior - -You can configure various aspects of the logging system: - -```java -// Configure logging to debug output with minimum severity level -Logging.logToDebug(Logging.Severity.INFO); - -// Enable/disable thread ID in log messages -Logging.logThreads(true); - -// Enable/disable timestamps in log messages -Logging.logTimestamps(true); -``` - -### Custom Log Sinks - -You can implement custom log handlers by creating a class that implements the `LogSink` interface: - -```java -import dev.onvoid.webrtc.logging.LogSink; -import dev.onvoid.webrtc.logging.Logging; -import dev.onvoid.webrtc.logging.Logging.Severity; - -public class CustomLogSink implements LogSink { - - @Override - public void onLogMessage(Severity severity, String message) { - // Process log messages as needed - // For example, write to a file, send to a server, or display in UI - System.out.println("[" + severity + "] " + message); - } -} -``` - -Register your custom log sink to receive log messages: - -```java -// Create and register a log sink for messages with INFO severity or higher -CustomLogSink logSink = new CustomLogSink(); -Logging.addLogSink(Logging.Severity.INFO, logSink); -``` - -The log sink will receive all log messages with a severity level equal to or higher than the specified minimum level. - -## Integration with Other Logging Frameworks - -If you're using a different logging framework like Log4j or SLF4J, you can create a bridge by implementing a custom `LogSink` that forwards messages to your preferred logging system: - -```java -import dev.onvoid.webrtc.logging.LogSink; -import dev.onvoid.webrtc.logging.Logging; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class Slf4jLogSink implements LogSink { - - private static final Logger logger = LoggerFactory.getLogger("WebRTC"); - - @Override - public void onLogMessage(Logging.Severity severity, String message) { - switch (severity) { - case VERBOSE: - logger.trace(message); - break; - case INFO: - logger.info(message); - break; - case WARNING: - logger.warn(message); - break; - case ERROR: - logger.error(message); - break; - default: - // Do nothing for NONE - } - } -} -``` - -Then register this sink with the WebRTC logging system: - -```java -Logging.addLogSink(Logging.Severity.VERBOSE, new Slf4jLogSink()); -``` - -This approach allows you to integrate WebRTC's native logging with your application's existing logging infrastructure. - -## Conclusion -By using the provided methods and custom log sinks, you can effectively capture, process, and manage log messages to aid in debugging and monitoring your application. Whether you choose to use the native logging capabilities or integrate with existing logging frameworks, the WebRTC logging system is designed to be adaptable to your needs. \ No newline at end of file diff --git a/docs/guide/monitoring/rtc-stats.md b/docs/guide/monitoring/rtc-stats.md deleted file mode 100644 index 9a687da..0000000 --- a/docs/guide/monitoring/rtc-stats.md +++ /dev/null @@ -1,395 +0,0 @@ -# RTC Stats - -This guide explains how to use WebRTC statistics (RTC Stats) with the webrtc-java library. RTC Stats provide detailed metrics and information about the state and performance of your WebRTC connections. - -## Overview - -WebRTC statistics allow you to: -- Monitor the quality of audio and video streams -- Track network performance metrics -- Diagnose connection issues -- Gather information about codecs, candidates, and data channels -- Analyze media source characteristics - -Statistics are collected through the `RTCPeerConnection` and are delivered asynchronously via callback. - -## Understanding RTC Stats Classes - -The webrtc-java library provides several classes for working with statistics: - -### RTCStats - -The `RTCStats` class represents statistics for a specific monitored object at a specific moment in time. Each `RTCStats` object contains: - -- `timestamp`: When the stats were collected (in microseconds since UNIX epoch) -- `type`: An enum value indicating the type of stats (from `RTCStatsType`) -- `id`: A unique identifier for the object that was inspected -- `attributes`: A map of key-value pairs containing the actual statistics data - -### RTCStatsReport - -The `RTCStatsReport` class contains a collection of `RTCStats` objects gathered at the same time. It provides: - -- A map of `RTCStats` objects, accessible via the `getStats()` method -- A timestamp indicating when the report was generated - -### RTCStatsType - -The `RTCStatsType` enum defines the different types of statistics that can be collected: - -```java -public enum RTCStatsType { - CODEC, // Codec statistics - INBOUND_RTP, // Incoming RTP stream statistics - OUTBOUND_RTP, // Outgoing RTP stream statistics - REMOTE_INBOUND_RTP, // Remote endpoint's incoming RTP statistics - REMOTE_OUTBOUND_RTP, // Remote endpoint's outgoing RTP statistics - MEDIA_SOURCE, // Media source statistics - CSRC, // Contributing source statistics - PEER_CONNECTION, // Peer connection statistics - DATA_CHANNEL, // Data channel statistics - STREAM, // MediaStream statistics - TRACK, // MediaStreamTrack statistics - SENDER, // RTP sender statistics - RECEIVER, // RTP receiver statistics - TRANSPORT, // Transport statistics - CANDIDATE_PAIR, // ICE candidate pair statistics - LOCAL_CANDIDATE, // Local ICE candidate statistics - REMOTE_CANDIDATE, // Remote ICE candidate statistics - CERTIFICATE, // Certificate statistics - ICE_SERVER // ICE server statistics -} -``` - -## Collecting Statistics - -### Getting Stats for the Entire Connection - -To collect statistics for the entire peer connection: - -```java -import dev.onvoid.webrtc.RTCPeerConnection; -import dev.onvoid.webrtc.RTCStats; -import dev.onvoid.webrtc.RTCStatsReport; -import dev.onvoid.webrtc.RTCStatsCollectorCallback; - -// Assuming you already have an RTCPeerConnection -RTCPeerConnection peerConnection = /* your peer connection */; - -// Request statistics -peerConnection.getStats(new RTCStatsCollectorCallback() { - @Override - public void onStatsDelivered(RTCStatsReport report) { - // Process the stats report - System.out.println("Stats collected at: " + report.getTimestamp()); - - // Access all stats in the report - Map stats = report.getStats(); - System.out.println("Number of stats objects: " + stats.size()); - - // Process individual stats objects - for (RTCStats stat : stats.values()) { - System.out.println("Stat type: " + stat.getType()); - System.out.println("Stat ID: " + stat.getId()); - - // Access the attributes - Map attributes = stat.getAttributes(); - for (Map.Entry entry : attributes.entrySet()) { - System.out.println(entry.getKey() + ": " + entry.getValue()); - } - } - } -}); -``` - -You can also use a lambda expression for more concise code: - -```java -peerConnection.getStats(report -> { - // Process the stats report - System.out.println("Stats report received with " + report.getStats().size() + " stats objects"); -}); -``` - -### Getting Stats for a Specific Sender or Receiver - -You can also collect statistics for a specific RTP sender or receiver: - -```java -// For a specific sender -RTCRtpSender sender = /* your RTP sender */; -peerConnection.getStats(sender, report -> { - // Process sender stats - System.out.println("Sender stats received"); -}); - -// For a specific receiver -RTCRtpReceiver receiver = /* your RTP receiver */; -peerConnection.getStats(receiver, report -> { - // Process receiver stats - System.out.println("Receiver stats received"); -}); -``` - -## Working with Specific Stat Types - -Different stat types contain different attributes. Here are examples of how to work with some common stat types: - -### Inbound RTP Statistics - -```java -peerConnection.getStats(report -> { - for (RTCStats stats : report.getStats().values()) { - if (stats.getType() == RTCStatsType.INBOUND_RTP) { - Map attributes = stats.getAttributes(); - - // Access common inbound RTP attributes - Long packetsReceived = (Long) attributes.get("packetsReceived"); - Long bytesReceived = (Long) attributes.get("bytesReceived"); - Double jitter = (Double) attributes.get("jitter"); - Long packetsLost = (Long) attributes.get("packetsLost"); - - System.out.println("Inbound RTP Stats:"); - System.out.println("Packets received: " + packetsReceived); - System.out.println("Bytes received: " + bytesReceived); - System.out.println("Jitter (seconds): " + jitter); - System.out.println("Packets lost: " + packetsLost); - } - } -}); -``` - -### Outbound RTP Statistics - -```java -peerConnection.getStats(report -> { - for (RTCStats stats : report.getStats().values()) { - if (stats.getType() == RTCStatsType.OUTBOUND_RTP) { - Map attributes = stats.getAttributes(); - - // Access common outbound RTP attributes - Long packetsSent = (Long) attributes.get("packetsSent"); - Long bytesSent = (Long) attributes.get("bytesSent"); - - System.out.println("Outbound RTP Stats:"); - System.out.println("Packets sent: " + packetsSent); - System.out.println("Bytes sent: " + bytesSent); - } - } -}); -``` - -### Candidate Pair Statistics - -```java -peerConnection.getStats(report -> { - for (RTCStats stats : report.getStats().values()) { - if (stats.getType() == RTCStatsType.CANDIDATE_PAIR) { - Map attributes = stats.getAttributes(); - - // Access common candidate pair attributes - Boolean nominated = (Boolean) attributes.get("nominated"); - String state = (String) attributes.get("state"); - Long bytesSent = (Long) attributes.get("bytesSent"); - Long bytesReceived = (Long) attributes.get("bytesReceived"); - Double currentRoundTripTime = (Double) attributes.get("currentRoundTripTime"); - - System.out.println("ICE Candidate Pair Stats:"); - System.out.println("Nominated: " + nominated); - System.out.println("State: " + state); - System.out.println("Bytes sent: " + bytesSent); - System.out.println("Bytes received: " + bytesReceived); - System.out.println("Current RTT (seconds): " + currentRoundTripTime); - } - } -}); -``` - -## Monitoring Connection Quality - -You can periodically collect statistics to monitor the quality of your WebRTC connection: - -```java -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -// Create a scheduler -ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); - -// Schedule periodic stats collection -scheduler.scheduleAtFixedRate(() -> { - peerConnection.getStats(report -> { - // Process and analyze stats - analyzeConnectionQuality(report); - }); -}, 0, 2, TimeUnit.SECONDS); // Collect stats every 2 seconds - -// Example method to analyze connection quality -private void analyzeConnectionQuality(RTCStatsReport report) { - // Track packet loss - Long totalPacketsLost = 0L; - Long totalPacketsReceived = 0L; - - // Track jitter - Double maxJitter = 0.0; - - // Track round-trip time - Double currentRtt = 0.0; - - for (RTCStats stats : report.getStats().values()) { - Map attributes = stats.getAttributes(); - - if (stats.getType() == RTCStatsType.INBOUND_RTP) { - Long packetsLost = (Long) attributes.get("packetsLost"); - Long packetsReceived = (Long) attributes.get("packetsReceived"); - Double jitter = (Double) attributes.get("jitter"); - - if (packetsLost != null) totalPacketsLost += packetsLost; - if (packetsReceived != null) totalPacketsReceived += packetsReceived; - if (jitter != null && jitter > maxJitter) maxJitter = jitter; - } - else if (stats.getType() == RTCStatsType.CANDIDATE_PAIR) { - Double rtt = (Double) attributes.get("currentRoundTripTime"); - if (rtt != null) currentRtt = rtt; - } - } - - // Calculate packet loss percentage - double packetLossPercent = 0; - if (totalPacketsReceived + totalPacketsLost > 0) { - packetLossPercent = (totalPacketsLost * 100.0) / (totalPacketsReceived + totalPacketsLost); - } - - // Log or display the quality metrics - System.out.println("Connection Quality Metrics:"); - System.out.println("Packet Loss: " + String.format("%.2f%%", packetLossPercent)); - System.out.println("Max Jitter: " + String.format("%.2f ms", maxJitter * 1000)); - System.out.println("Round-Trip Time: " + String.format("%.2f ms", currentRtt * 1000)); - - // Determine overall quality - String qualityRating; - if (packetLossPercent < 1 && maxJitter < 0.030 && currentRtt < 0.100) { - qualityRating = "Excellent"; - } else if (packetLossPercent < 3 && maxJitter < 0.050 && currentRtt < 0.200) { - qualityRating = "Good"; - } else if (packetLossPercent < 8 && maxJitter < 0.100 && currentRtt < 0.300) { - qualityRating = "Fair"; - } else { - qualityRating = "Poor"; - } - - System.out.println("Overall Quality: " + qualityRating); -} - -// Don't forget to shut down the scheduler when done -// scheduler.shutdown(); -``` - -## Handling Asynchronous Stats Collection - -Since stats are collected asynchronously, you might need to coordinate with other operations. Here's an example using a CountDownLatch: - -```java -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - -public RTCStatsReport collectStatsSync(RTCPeerConnection peerConnection, long timeoutMs) throws InterruptedException { - CountDownLatch latch = new CountDownLatch(1); - AtomicReference reportRef = new AtomicReference<>(); - - peerConnection.getStats(report -> { - reportRef.set(report); - latch.countDown(); - }); - - // Wait for stats to be delivered or timeout - if (!latch.await(timeoutMs, TimeUnit.MILLISECONDS)) { - throw new RuntimeException("Timed out waiting for stats"); - } - - return reportRef.get(); -} - -// Usage -try { - RTCStatsReport report = collectStatsSync(peerConnection, 5000); - // Process the report -} catch (InterruptedException e) { - System.err.println("Stats collection was interrupted: " + e.getMessage()); -} catch (RuntimeException e) { - System.err.println("Stats collection failed: " + e.getMessage()); -} -``` - -## Best Practices - -1. **Don't Collect Too Frequently**: Collecting stats is resource-intensive. For most applications, collecting stats every 1-2 seconds is sufficient. - -2. **Handle Null Values**: Some attributes might be null or missing depending on the state of the connection and the browser implementation. Always check for null values before using them. - -3. **Type Casting**: The attributes in the stats objects are returned as generic Objects. You need to cast them to the appropriate type (Boolean, Long, Double, String, etc.) before using them. - -4. **Trend Analysis**: Individual stats snapshots are useful, but tracking trends over time provides more valuable insights. Consider storing historical data to analyze trends. - -5. **Focus on Relevant Stats**: Depending on your use case, focus on the most relevant stats: - - For video quality: frame rate, resolution, packets lost - - For audio quality: jitter, packets lost - - For network performance: round-trip time, bandwidth - -6. **Correlation**: Correlate stats with user experience. For example, if users report poor quality, check the stats during that time to identify potential issues. - -7. **Logging**: Log stats periodically and especially when issues occur to help with debugging. - -## Common Attributes by Stat Type - -Different stat types have different attributes. Here are some common attributes for each type: - -### INBOUND_RTP -- packetsReceived -- bytesReceived -- packetsLost -- jitter -- framesDecoded (video) -- framesDropped (video) -- audioLevel (audio) - -### OUTBOUND_RTP -- packetsSent -- bytesSent -- retransmittedPacketsSent -- framesSent (video) -- framesEncoded (video) -- targetBitrate - -### CANDIDATE_PAIR -- nominated -- state -- bytesSent -- bytesReceived -- currentRoundTripTime -- availableOutgoingBitrate -- availableIncomingBitrate - -### TRANSPORT -- bytesSent -- bytesReceived -- dtlsState -- selectedCandidatePairId - -### MEDIA_SOURCE -- trackIdentifier -- kind -- audioLevel (audio) -- totalAudioEnergy (audio) -- width (video) -- height (video) -- frames (video) -- framesPerSecond (video) - -Remember that the available attributes may vary depending on the state of the connection. - -## Conclusion - -WebRTC statistics provide essential insights into the performance and health of your real-time communications. By leveraging the RTC Stats API in webrtc-java, you can monitor connection quality, diagnose issues, and optimize your application's performance. The ability to collect detailed metrics on packets, jitter, latency, and more allows you to make data-driven decisions. \ No newline at end of file diff --git a/docs/guide/networking/port-allocator-config.md b/docs/guide/networking/port-allocator-config.md deleted file mode 100644 index fa15338..0000000 --- a/docs/guide/networking/port-allocator-config.md +++ /dev/null @@ -1,105 +0,0 @@ -# Port Allocator Configuration (ICE) - -This guide explains how to configure the ICE port allocator using `dev.onvoid.webrtc.PortAllocatorConfig` and how to use it with `RTCConfiguration` when creating a peer connection. - -The Port Allocator controls: -- The local ephemeral port range used for gathering ICE candidates (HOST, SRFLX, RELAY). -- Transport behavior via bit flags that mirror native WebRTC PortAllocator flags (e.g., disable TCP candidates, enable IPv6, etc.). - -When you need to restrict the ports your application binds to (e.g., to satisfy firewall rules) or tweak which transport types are gathered, use `PortAllocatorConfig`. - -## API Overview - -`PortAllocatorConfig` exposes three fields: -- `minPort` (int): Minimum UDP/TCP port to use for candidate gathering (inclusive). Set to 0 to leave unspecified. -- `maxPort` (int): Maximum UDP/TCP port to use for candidate gathering (inclusive). Set to 0 to leave unspecified. -- `flags` (int): Bitwise OR of allocator flags (default 0). - -Notes: -- If both `minPort` and `maxPort` are set to non‑zero values, `minPort` must be less than or equal to `maxPort`. -- A value of 0 for either `minPort` or `maxPort` means "not specified" and the native defaults are used. - -Convenience methods are provided to toggle specific behaviors and to combine flags: -- `setFlag(int flag)`, `clearFlag(int flag)`, `isFlagEnabled(int flag)` -- Boolean helpers like `setDisableTcp(boolean)`, `isTcpDisabled()`, etc. - -## Supported Flags - -The following flags mirror WebRTC's native PortAllocator flags. You can use them directly via `setFlag/clearFlag` or through the boolean helpers. - -- `PORTALLOCATOR_DISABLE_UDP` — Disable local UDP socket allocation for host candidates. -- `PORTALLOCATOR_DISABLE_STUN` — Disable STUN candidate gathering (server reflexive). -- `PORTALLOCATOR_DISABLE_RELAY` — Disable TURN relay candidate gathering. -- `PORTALLOCATOR_DISABLE_TCP` — Disable local TCP candidate gathering. -- `PORTALLOCATOR_ENABLE_IPV6` — Enable IPv6 support. -- `PORTALLOCATOR_ENABLE_SHARED_SOCKET` — Enable shared UDP socket mode (platform/stack‑dependent behavior). -- `PORTALLOCATOR_ENABLE_STUN_RETRANSMIT_ATTRIBUTE` — Include STUN retransmit attribute on requests. -- `PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION` — Do not enumerate network adapters. -- `PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE` — Do not generate a default local candidate. -- `PORTALLOCATOR_DISABLE_UDP_RELAY` — Disable UDP TURN relay. -- `PORTALLOCATOR_DISABLE_COSTLY_NETWORKS` — Avoid cellular/expensive networks for candidate gathering. -- `PORTALLOCATOR_ENABLE_IPV6_ON_WIFI` — Allow IPv6 over Wi‑Fi. -- `PORTALLOCATOR_ENABLE_ANY_ADDRESS_PORTS` — Allow binding to any‑address (0.0.0.0/::) ports. -- `PORTALLOCATOR_DISABLE_LINK_LOCAL_NETWORKS` — Avoid link‑local network interfaces. - -## Basic Usage - -You configure the port allocator on the `RTCConfiguration` before creating the `RTCPeerConnection`. - -```java -RTCConfiguration cfg = new RTCConfiguration(); - -// Constrain ephemeral port range for HOST candidates -cfg.portAllocatorConfig.minPort = 48000; -cfg.portAllocatorConfig.maxPort = 48100; - -// Example: Disable TCP candidates, keep UDP enabled (default) -cfg.portAllocatorConfig.setDisableTcp(true); - -// Optional: Enable IPv6 support -// cfg.portAllocatorConfig.setEnableIpv6(true); - -RTCPeerConnection pc = factory.createPeerConnection(cfg, observer); -``` - -## Using Flags Directly - -You can combine flags using bitwise OR and set them at once: - -```java -int flags = PortAllocatorConfig.PORTALLOCATOR_DISABLE_TCP - | PortAllocatorConfig.PORTALLOCATOR_DISABLE_RELAY - | PortAllocatorConfig.PORTALLOCATOR_ENABLE_IPV6; - -RTCConfiguration cfg = new RTCConfiguration(); -cfg.portAllocatorConfig.minPort = 50000; -cfg.portAllocatorConfig.maxPort = 50100; -cfg.portAllocatorConfig.flags = flags; - -RTCPeerConnection pc = factory.createPeerConnection(cfg, observer); -``` - -Or use the fluent helpers: - -```java -cfg.portAllocatorConfig - .setDisableStun(true) - .setDisableRelay(true) - .setEnableSharedSocket(true); -``` - -## Tips and Troubleshooting - -- Port Range Validity: Ensure `minPort <= maxPort` when both are set. If either is 0, the native default behavior applies. -- Firewalls/NATs: When running behind strict firewalls, restrict the host candidate port range to an allowed window and ensure your firewall allows outbound UDP for STUN/TURN as needed. -- Disabling Candidates: Disabling STUN and RELAY will limit you to host candidates, which may prevent connectivity across NATs. Use with care. -- TCP Candidates: Disabling TCP can speed up gathering and reduce unwanted candidates, but may reduce connectivity options in restrictive environments. -- IPv6: Enabling IPv6 may improve connectivity on IPv6‑capable networks; consider also `setEnableIpv6OnWifi(true)` when applicable. - -## Related API - -- `RTCConfiguration` — holds `portAllocatorConfig` used by `PeerConnectionFactory#createPeerConnection`. -- `RTCPeerConnection` — creating a peer connection triggers ICE gathering. -- `RTCIceServer` — define STUN/TURN servers for non‑host candidates. - -For the full API, see the JavaDoc for `PortAllocatorConfig` and `RTCConfiguration`. diff --git a/docs/guide/video/camera-capture.md b/docs/guide/video/camera-capture.md deleted file mode 100644 index d3ea772..0000000 --- a/docs/guide/video/camera-capture.md +++ /dev/null @@ -1,299 +0,0 @@ -# Camera Video - -This guide focuses on setting up a peer connection with camera video capture capabilities, which allows you to capture and stream video from connected cameras in your WebRTC connection. - -## Camera Video Source Selection - -To enable camera video capture, you need to: - -1. List available video devices (cameras) -2. Create and configure a `VideoDeviceSource` -3. Create a video track with the camera source -4. Add the track to your peer connection - -### Getting Available Cameras and Capabilities - -Before configuring your camera source, you may want to check the supported resolutions and frame rates: - -```java -import dev.onvoid.webrtc.media.MediaDevices; -import dev.onvoid.webrtc.media.video.VideoDevice; -import dev.onvoid.webrtc.media.video.VideoCaptureCapability; -import java.util.List; - -// Get all cameras -List cameras = MediaDevices.getVideoCaptureDevices(); -if (cameras.isEmpty()) { - System.out.println("No cameras found"); - return; -} - -// Get the first camera -VideoDevice camera = cameras.get(0); -System.out.println("Camera: " + camera.getName()); - -// Get camera capabilities -List capabilities = MediaDevices.getVideoCaptureCapabilities(camera); - -// Print camera capabilities -for (VideoCaptureCapability capability : capabilities) { - System.out.println(" Resolution: " + capability.width + "x" + capability.height); - System.out.println(" Frame Rate: " + capability.frameRate + " fps"); -} -``` - -### Creating and Configuring a VideoDeviceSource - -The `VideoDeviceSource` class allows you to capture video from a camera: - -```java -import dev.onvoid.webrtc.media.video.VideoDeviceSource; -import dev.onvoid.webrtc.media.video.VideoDevice; -import dev.onvoid.webrtc.media.video.VideoCaptureCapability; - -// Create a video device source -VideoDeviceSource videoSource = new VideoDeviceSource(); - -// Select a specific camera to capture from -VideoDevice camera = cameras.get(0); // Use the first available camera -videoSource.setVideoCaptureDevice(camera); - -// Configure the capture capability (optional) -// Choose a capability from the list obtained earlier -VideoCaptureCapability capability = capabilities.get(0); // Use the first available capability -videoSource.setVideoCaptureCapability(capability); - -// Start capturing -videoSource.start(); -``` - -### Creating a Video Track with the Camera Source - -Once you have configured your camera video source, you can create a video track: - -```java -import dev.onvoid.webrtc.PeerConnectionFactory; -import dev.onvoid.webrtc.media.video.VideoTrack; - -// Create a PeerConnectionFactory -PeerConnectionFactory factory = new PeerConnectionFactory(); - -// Create a video track with the camera source -VideoTrack videoTrack = factory.createVideoTrack("video0", videoSource); -``` - -### Adding the Track to a Peer Connection - -Add the video track to your peer connection: - -```java -import java.util.ArrayList; -import java.util.List; -import dev.onvoid.webrtc.RTCPeerConnection; - -// Assuming you already have a configured RTCPeerConnection -RTCPeerConnection peerConnection = factory.createPeerConnection(config, observer); - -// Add the track to the peer connection -List streamIds = new ArrayList<>(); -streamIds.add("stream1"); -peerConnection.addTrack(videoTrack, streamIds); -``` - -## Additional Features - -The `VideoDeviceSource` provides additional methods for controlling the camera capture: - -### Resource Management - -Always properly dispose of resources when done: - -```java -// Dispose of resources when done -videoSource.stop(); -videoSource.dispose(); -``` - -## Receiving Video Frames - -Once you have set up your camera video source and peer connection, you'll likely want to receive and process the video frames. This section explains how to receive both local and remote video frames. - -### Creating a VideoTrackSink - -To receive video frames, you need to implement the `VideoTrackSink` interface and add it to a video track: - -```java -import dev.onvoid.webrtc.media.video.VideoFrame; -import dev.onvoid.webrtc.media.video.VideoTrackSink; - -// Create a class that implements VideoTrackSink -public class MyVideoSink implements VideoTrackSink { - @Override - public void onVideoFrame(VideoFrame frame) { - // Process the video frame - System.out.printf("Received frame: %dx%d%n", - frame.buffer.getWidth(), frame.buffer.getHeight()); - - // IMPORTANT: Always release the frame when done to prevent memory leaks - frame.release(); - } -} -``` - -### Receiving Local Video Frames - -To receive frames from your local camera: - -```java -// Create your video sink -MyVideoSink localVideoSink = new MyVideoSink(); - -// Add the sink to your local video track -videoTrack.addSink(localVideoSink); - -// Later, when you're done, remove the sink -videoTrack.removeSink(localVideoSink); -``` - -### Receiving Remote Video Frames - -To receive frames from a remote peer, you need to add a sink to the remote video track when it's received. This is typically done in the `onTrack` method of your `PeerConnectionObserver`: - -```java -import dev.onvoid.webrtc.PeerConnectionObserver; -import dev.onvoid.webrtc.RTCRtpTransceiver; -import dev.onvoid.webrtc.media.MediaStreamTrack; -import dev.onvoid.webrtc.media.video.VideoTrack; - -public class MyPeerConnectionObserver implements PeerConnectionObserver { - private final MyVideoSink remoteVideoSink = new MyVideoSink(); - - // Other methods omitted for brevity... - - @Override - public void onTrack(RTCRtpTransceiver transceiver) { - MediaStreamTrack track = transceiver.getReceiver().getTrack(); - String kind = track.getKind(); - - if (kind.equals(MediaStreamTrack.VIDEO_TRACK_KIND)) { - VideoTrack videoTrack = (VideoTrack) track; - videoTrack.addSink(remoteVideoSink); - System.out.println("Added sink to remote video track"); - } - } - - // Make sure to clean up when done - public void dispose() { - // Remove sinks from any tracks they were added to - } -} -``` - -## Processing Video Frames - -When processing video frames, consider these important points: - -1. **Frame Properties**: Each `VideoFrame` contains: - - A `VideoFrameBuffer` with the actual pixel data - - Width and height information - - Rotation value - - Timestamp - -2. **Memory Management**: Always call `frame.release()` when you're done with a frame to prevent memory leaks. - -3. **Performance Considerations**: Frame processing happens on the WebRTC thread, so keep your processing efficient. For heavy processing, consider: - - Copying the frame data and processing it on a separate thread - - Using a frame queue with a dedicated processing thread - - Skipping frames if processing can't keep up with the frame rate - -### Converting VideoFrame to other pixel formats - -For converting I420 frames to UI-friendly pixel formats (e.g., RGBA) and other pixel format conversions, use the `VideoBufferConverter` utility. - -- See: [Video Buffer Converter](/tools/video/video-buffer-converter) - -### Scaling Video Frames - -Sometimes you may need to resize video frames to a different resolution, either to reduce processing requirements or to fit a specific display area. The `VideoFrameBuffer` interface provides a `cropAndScale` method that can be used for both cropping and scaling operations: - -```java -import dev.onvoid.webrtc.media.video.VideoFrame; -import dev.onvoid.webrtc.media.video.VideoFrameBuffer; -import dev.onvoid.webrtc.media.video.VideoTrackSink; - -public class ScalingVideoSink implements VideoTrackSink { - private final int targetWidth; - private final int targetHeight; - - public ScalingVideoSink(int targetWidth, int targetHeight) { - this.targetWidth = targetWidth; - this.targetHeight = targetHeight; - } - - @Override - public void onVideoFrame(VideoFrame frame) { - try { - // Get the original frame buffer - VideoFrameBuffer originalBuffer = frame.buffer; - int originalWidth = originalBuffer.getWidth(); - int originalHeight = originalBuffer.getHeight(); - - // Scale the frame to the target resolution - // For scaling only (no cropping), use the original dimensions for the crop region - VideoFrameBuffer scaledBuffer = originalBuffer.cropAndScale( - 0, 0, // No cropping from top-left (cropX, cropY) - originalWidth, originalHeight, // Use full frame width and height - targetWidth, targetHeight // Scale to target dimensions - ); - - // Create a new frame with the scaled buffer - VideoFrame scaledFrame = new VideoFrame(scaledBuffer, frame.rotation, frame.timestampNs); - - // Process the scaled frame - System.out.printf("Scaled frame from %dx%d to %dx%d%n", - originalWidth, originalHeight, scaledBuffer.getWidth(), scaledBuffer.getHeight()); - - // Don't forget to release both frames when done - scaledFrame.release(); - } finally { - // Always release the original frame - frame.release(); - } - } -} -``` - -This scaling process works as follows: - -1. Get the original frame buffer and its dimensions. - -2. Call `cropAndScale` on the original buffer with parameters: - - `cropX = 0`, `cropY = 0`: Start from the top-left corner (no cropping) - - `cropWidth = originalWidth`, `cropHeight = originalHeight`: Use the full frame (no cropping) - - `scaleWidth = targetWidth`, `scaleHeight = targetHeight`: Scale to the desired dimensions - -3. Create a new `VideoFrame` with the scaled buffer, preserving the original rotation and timestamp. - -4. Process the scaled frame as needed. - -5. Release both the scaled frame and the original frame to prevent memory leaks. - -Note that scaling is a computationally expensive operation, especially for high-resolution frames. Consider the performance implications when choosing target dimensions and how frequently you scale frames. - -## Best Practices - -When implementing camera capture in your application, consider these best practices: - -1. **Check for available cameras**: Always check if cameras are available before trying to use them. -2. **Handle no cameras gracefully**: Provide a fallback mechanism if no cameras are available. -3. **Let users select cameras**: If multiple cameras are available, let users choose which one to use. -4. **Select appropriate resolution**: Choose a resolution that balances quality and performance. -5. **Properly manage resources**: Always stop and dispose of video sources when they're no longer needed. -6. **Handle device changes**: Implement device change listeners to handle cameras being connected or disconnected. -7. **Consider privacy concerns**: In some applications, you may need to request permission to use the camera. - -## Conclusion - -This guide has demonstrated how to set up a WebRTC peer connection with camera video capture capabilities and how to receive and process both local and remote video frames. - -Camera capture is essential for video conferencing applications, video chat, remote interviews, and any other applications where face-to-face communication is important. \ No newline at end of file diff --git a/docs/guide/video/custom-video-source.md b/docs/guide/video/custom-video-source.md deleted file mode 100644 index 913958a..0000000 --- a/docs/guide/video/custom-video-source.md +++ /dev/null @@ -1,192 +0,0 @@ -# Custom Video Source - -This guide explains how to use the `CustomVideoSource` class to push video frames from external sources directly to the WebRTC video pipeline. - -## Overview - -The `CustomVideoSource` allows you to provide video frames from custom sources such as: -- Video files -- Network streams -- Generated video (patterns, animations, etc.) -- Video processing libraries -- Any other source of raw video frames - -This is particularly useful when you need to: -- Stream pre-recorded video -- Process video before sending it -- Generate synthetic video -- Integrate with external video APIs - -## Basic Usage - -### Creating a Custom Video Source - -To use a custom video source, you first need to create an instance: - -```java -import dev.onvoid.webrtc.media.video.CustomVideoSource; - -// Create a new CustomVideoSource instance -CustomVideoSource videoSource = new CustomVideoSource(); -``` - -### Creating a Video Track - -Once you have a custom video source, you can create a video track with it: - -```java -import dev.onvoid.webrtc.PeerConnectionFactory; -import dev.onvoid.webrtc.media.video.VideoTrack; - -// Create a PeerConnectionFactory (you should already have this in your WebRTC setup) -PeerConnectionFactory factory = new PeerConnectionFactory(); - -// Create a video track using the custom video source -VideoTrack videoTrack = factory.createVideoTrack("video-track-id", videoSource); -``` - -### Pushing Video Frames - -The key feature of `CustomVideoSource` is the ability to push video frames directly to the WebRTC pipeline: - -```java -import dev.onvoid.webrtc.media.video.VideoFrame; -import dev.onvoid.webrtc.media.video.NativeI420Buffer; - -// Create a video frame with appropriate dimensions and format -int width = 640; -int height = 480; -NativeI420Buffer buffer = NativeI420Buffer.allocate(width, height); - -// Fill the buffer with your video data -// ... - -// Create a video frame with the buffer -VideoFrame frame = new VideoFrame(buffer, System.nanoTime()); - -// Push the frame to the WebRTC pipeline -videoSource.pushFrame(frame); - -// Don't forget to release the frame when done -frame.dispose(); -``` - -## Video Format Considerations - -When pushing video frames, you need to consider the following: - -### Resolution -- Common resolutions: 320x240, 640x480, 1280x720, 1920x1080 -- Higher resolutions require more bandwidth and processing power - -### Frame Rate -- Common frame rates: 15, 24, 30, 60 fps -- Higher frame rates provide smoother video but require more bandwidth - -### Color Format -- WebRTC primarily uses I420 (YUV 4:2:0) format -- You may need to convert from other formats (RGB, RGBA, NV12, etc.) - -## Advanced Usage - -### Continuous Video Streaming - -For continuous streaming, you'll typically push video frames in a separate thread: - -```java -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -public class VideoStreamer { - private final CustomVideoSource videoSource; - private final ScheduledExecutorService executor; - private final int width = 640; - private final int height = 480; - private final int frameRate = 30; - - public VideoStreamer(CustomVideoSource videoSource) { - this.videoSource = videoSource; - this.executor = Executors.newSingleThreadScheduledExecutor(); - } - - public void start() { - // Schedule task to run at the desired frame rate - int periodMs = 1000 / frameRate; - executor.scheduleAtFixedRate(this::pushNextVideoFrame, 0, periodMs, TimeUnit.MILLISECONDS); - } - - public void stop() { - executor.shutdown(); - } - - private void pushNextVideoFrame() { - try { - // Create a buffer for the frame - NativeI420Buffer buffer = NativeI420Buffer.allocate(width, height); - - // Fill buffer with your video data - // ... - - // Create and push the frame - VideoFrame frame = new VideoFrame(buffer, System.nanoTime()); - videoSource.pushFrame(frame); - - // Release resources - frame.dispose(); - } - catch (Exception e) { - e.printStackTrace(); - } - } -} -``` - -## Integration with Video Tracks - -### Adding Sinks to Monitor Video - -You can add sinks to the video track to monitor the video frames: - -```java -import dev.onvoid.webrtc.media.video.VideoTrackSink; - -// Create a sink to monitor the video frames -VideoTrackSink monitorSink = frame -> { - System.out.println("Received frame: " + - frame.getBuffer().getWidth() + "x" + - frame.getBuffer().getHeight() + ", " + - "rotation: " + frame.getRotation() + ", " + - "timestamp: " + frame.getTimestampUs() + "µs"); - - // You can process or analyze the frame here - // Note: Don't modify the frame directly -}; - -// Add the sink to the video track -videoTrack.addSink(monitorSink); - -// When done, remove the sink -videoTrack.removeSink(monitorSink); -``` - -## Cleanup - -When you're done with the custom video source, make sure to clean up resources: - -```java -// Dispose of the video track -videoTrack.dispose(); - -// Dispose of the video source to prevent memory leaks -videoSource.dispose(); - -// If you're using a scheduled executor for pushing frames -videoStreamer.stop(); -``` - -## Conclusion - -The `CustomVideoSource` provides a flexible way to integrate external video sources with WebRTC. By understanding the video format parameters and properly managing the video frame flow, you can create applications that use custom video from virtually any source. - -For more information on video processing and other WebRTC features, refer to the additional guides in the documentation. \ No newline at end of file diff --git a/docs/guide/video/desktop-capture.md b/docs/guide/video/desktop-capture.md deleted file mode 100644 index 6f4e86b..0000000 --- a/docs/guide/video/desktop-capture.md +++ /dev/null @@ -1,170 +0,0 @@ -# Desktop Video - -This guide focuses on setting up a peer connection with desktop video capture capabilities, which allows you to capture and stream content from your screens or application windows in your WebRTC connection. - -## Desktop Video Source Selection - -To enable desktop video capture, you need to: - -1. List available desktop sources (screens and windows) -2. Create and configure a `VideoDesktopSource` -3. Create a video track with the desktop source -4. Add the track to your peer connection - -### Listing Available Desktop Sources - -The library provides classes to list available screens and windows: - -```java -import dev.onvoid.webrtc.media.video.desktop.DesktopSource; -import dev.onvoid.webrtc.media.video.desktop.ScreenCapturer; -import dev.onvoid.webrtc.media.video.desktop.WindowCapturer; -import java.util.List; - -// Get available screens -ScreenCapturer screenCapturer = new ScreenCapturer(); -List screens = screenCapturer.getDesktopSources(); -System.out.println("Available screens:"); -for (DesktopSource screen : screens) { - System.out.printf(" Screen: %s (ID: %d)%n", screen.title, screen.id); -} - -// Get available windows -WindowCapturer windowCapturer = new WindowCapturer(); -List windows = windowCapturer.getDesktopSources(); -System.out.println("Available windows:"); -for (DesktopSource window : windows) { - System.out.printf(" Window: %s (ID: %d)%n", window.title, window.id); -} - -// Clean up the capturers after use -screenCapturer.dispose(); -windowCapturer.dispose(); -``` - -### Creating and Configuring a VideoDesktopSource - -The `VideoDesktopSource` class allows you to capture video from a desktop source: - -```java -import dev.onvoid.webrtc.media.video.VideoDesktopSource; - -// Create a desktop video source -VideoDesktopSource videoSource = new VideoDesktopSource(); - -// Configure the desktop video source -// Set frame rate (e.g., 30 fps) -videoSource.setFrameRate(30); - -// Set maximum frame size (e.g., 1920x1080) -videoSource.setMaxFrameSize(1920, 1080); - -// Select a specific source to capture -// For a screen (isWindow = false) -videoSource.setSourceId(screenId, false); -// OR for a window (isWindow = true) -videoSource.setSourceId(windowId, true); - -// Start capturing -videoSource.start(); -``` - -### Creating a Video Track with the Desktop Source - -Once you have configured your desktop video source, you can create a video track: - -```java -import dev.onvoid.webrtc.PeerConnectionFactory; -import dev.onvoid.webrtc.media.video.VideoTrack; - -// Create a PeerConnectionFactory -PeerConnectionFactory factory = new PeerConnectionFactory(); - -// Create a video track with the desktop source -VideoTrack videoTrack = factory.createVideoTrack("video0", videoSource); -``` - -### Adding the Track to a Peer Connection - -Add the video track to your peer connection: - -```java -import java.util.ArrayList; -import java.util.List; -import dev.onvoid.webrtc.RTCPeerConnection; - -// Assuming you already have a configured RTCPeerConnection -RTCPeerConnection peerConnection = factory.createPeerConnection(config, observer); - -// Add the track to the peer connection -List streamIds = new ArrayList<>(); -streamIds.add("stream1"); -peerConnection.addTrack(videoTrack, streamIds); -``` - -## Additional Features - -The `VideoDesktopSource` provides additional methods for controlling the desktop capture: - -### Source Selection - -You can change the capture source at runtime: - -```java -// Switch to a different screen -videoSource.setSourceId(newScreenId, false); - -// Switch to a window -videoSource.setSourceId(windowId, true); -``` - -### Capture Configuration - -You can adjust capture settings: - -```java -// Change frame rate -videoSource.setFrameRate(15); // Set to 15 fps - -// Change maximum resolution -videoSource.setMaxFrameSize(1280, 720); // Set to 720p -``` - -### Resource Management - -Always properly dispose of resources when done: - -```java -// Dispose of resources when done -videoSource.stop(); -videoSource.dispose(); -``` - -### Handling Source Changes - -If desktop sources might change during your application's lifecycle (e.g., new windows opening or screens connecting), you should periodically refresh the source list: - -```java -// Refresh the list of available sources -ScreenCapturer screenCapturer = new ScreenCapturer(); -List updatedScreens = screenCapturer.getDesktopSources(); - -WindowCapturer windowCapturer = new WindowCapturer(); -List updatedWindows = windowCapturer.getDesktopSources(); - -// Clean up -screenCapturer.dispose(); -windowCapturer.dispose(); -``` - -## Conclusion - -This guide has demonstrated how to set up a WebRTC peer connection with desktop video capture capabilities. -When implementing desktop capture in your application, remember to: - -- Always dispose of resources properly to prevent memory leaks -- Periodically refresh source lists to handle dynamic changes in available screens and windows -- Consider the performance implications of higher resolutions and frame rates -- Handle potential permission requirements on different operating systems - -Desktop capture is particularly useful for screen sharing applications, remote assistance tools, collaborative workspaces, and educational platforms where visual content sharing is essential. \ No newline at end of file diff --git a/docs/index.md b/docs/index.md deleted file mode 100644 index 443f50e..0000000 --- a/docs/index.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -layout: home - -hero: - name: "webrtc-java" - text: "Java native interface for WebRTC" - tagline: Build real‑time audio, video, and data with a clean Java API. - actions: - - theme: brand - text: Get Started - link: /guide/get-started - - theme: alt - text: What is webrtc-java? - link: /guide/introduction - - theme: alt - text: Sponsor this project - link: https://buymeacoffee.com/devopvoid - image: - src: /logo.png - alt: webrtc-java - -features: - - title: Cross-platform - details: Use the same Java API across Windows, macOS, and Linux with prebuilt native bindings. Ideal for desktop apps and server‑side media services. - - title: Native performance - details: Thin JNI layer with minimal overhead, delivering near-native performance with minimal context switching between Java and native code. - - title: Audio and video streaming - details: Audio and video capture from cameras and microphones devices, with support for custom media sources for flexible streaming solutions. - - title: Screen Sharing - details: Share application windows or the full desktop with minimal setup; integrate screen capture streams like any other media stream. - - title: Data Channels - details: Reliable and unordered/ordered SCTP data channels for arbitrary messaging, file transfer, and app signaling. - - title: Statistics API for monitoring - details: Access WebRTC stats (bitrate, packet loss, jitter, RTT, frame rate, CPU) to monitor and optimize media quality. ---- - diff --git a/docs/package-lock.json b/docs/package-lock.json deleted file mode 100644 index d0c3423..0000000 --- a/docs/package-lock.json +++ /dev/null @@ -1,2261 +0,0 @@ -{ - "name": "webrtc-java", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "webrtc-java", - "devDependencies": { - "@types/node": "^24.3.1", - "vitepress": "^2.0.0-alpha.12" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.3.tgz", - "integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.2" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/types": { - "version": "7.28.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz", - "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@docsearch/css": { - "version": "4.0.0-beta.8", - "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-4.0.0-beta.8.tgz", - "integrity": "sha512-/ZlyvZCjIJM4aaOYoJpVNHPJckX7J5KIbt6IWjnZXvo0QAUI1aH976vKEJUC9olgUbE3LWafB8yuX4qoqahIQg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@docsearch/js": { - "version": "4.0.0-beta.8", - "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-4.0.0-beta.8.tgz", - "integrity": "sha512-elgqPYpykRQr5MlfqoO8U2uC3BcPgjUQhzmHt/H4lSzP7khJ9Jpv/cCB4tiZreXb6GkdRgWr5csiItNq6jjnhg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", - "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", - "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", - "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", - "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", - "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", - "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", - "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", - "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", - "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", - "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", - "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", - "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", - "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", - "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", - "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", - "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", - "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", - "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", - "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", - "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", - "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", - "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", - "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", - "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", - "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", - "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@iconify-json/simple-icons": { - "version": "1.2.50", - "resolved": "https://registry.npmjs.org/@iconify-json/simple-icons/-/simple-icons-1.2.50.tgz", - "integrity": "sha512-Z2ggRwKYEBB9eYAEi4NqEgIzyLhu0Buh4+KGzMPD6+xG7mk52wZJwLT/glDPtfslV503VtJbqzWqBUGkCMKOFA==", - "dev": true, - "license": "CC0-1.0", - "dependencies": { - "@iconify/types": "*" - } - }, - "node_modules/@iconify/types": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", - "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.29", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.29.tgz", - "integrity": "sha512-NIJgOsMjbxAXvoGq/X0gD7VPMQ8j9g0BiDaNjVNVjvl+iKXxL3Jre0v31RmBYeLEmkbj2s02v8vFTbUXi5XS2Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.0.tgz", - "integrity": "sha512-lVgpeQyy4fWN5QYebtW4buT/4kn4p4IJ+kDNB4uYNT5b8c8DLJDg6titg20NIg7E8RWwdWZORW6vUFfrLyG3KQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.50.0.tgz", - "integrity": "sha512-2O73dR4Dc9bp+wSYhviP6sDziurB5/HCym7xILKifWdE9UsOe2FtNcM+I4xZjKrfLJnq5UR8k9riB87gauiQtw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.0.tgz", - "integrity": "sha512-vwSXQN8T4sKf1RHr1F0s98Pf8UPz7pS6P3LG9NSmuw0TVh7EmaE+5Ny7hJOZ0M2yuTctEsHHRTMi2wuHkdS6Hg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.50.0.tgz", - "integrity": "sha512-cQp/WG8HE7BCGyFVuzUg0FNmupxC+EPZEwWu2FCGGw5WDT1o2/YlENbm5e9SMvfDFR6FRhVCBePLqj0o8MN7Vw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.50.0.tgz", - "integrity": "sha512-UR1uTJFU/p801DvvBbtDD7z9mQL8J80xB0bR7DqW7UGQHRm/OaKzp4is7sQSdbt2pjjSS72eAtRh43hNduTnnQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.50.0.tgz", - "integrity": "sha512-G/DKyS6PK0dD0+VEzH/6n/hWDNPDZSMBmqsElWnCRGrYOb2jC0VSupp7UAHHQ4+QILwkxSMaYIbQ72dktp8pKA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.50.0.tgz", - "integrity": "sha512-u72Mzc6jyJwKjJbZZcIYmd9bumJu7KNmHYdue43vT1rXPm2rITwmPWF0mmPzLm9/vJWxIRbao/jrQmxTO0Sm9w==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.50.0.tgz", - "integrity": "sha512-S4UefYdV0tnynDJV1mdkNawp0E5Qm2MtSs330IyHgaccOFrwqsvgigUD29uT+B/70PDY1eQ3t40+xf6wIvXJyg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.50.0.tgz", - "integrity": "sha512-1EhkSvUQXJsIhk4msxP5nNAUWoB4MFDHhtc4gAYvnqoHlaL9V3F37pNHabndawsfy/Tp7BPiy/aSa6XBYbaD1g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.50.0.tgz", - "integrity": "sha512-EtBDIZuDtVg75xIPIK1l5vCXNNCIRM0OBPUG+tbApDuJAy9mKago6QxX+tfMzbCI6tXEhMuZuN1+CU8iDW+0UQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.50.0.tgz", - "integrity": "sha512-BGYSwJdMP0hT5CCmljuSNx7+k+0upweM2M4YGfFBjnFSZMHOLYR0gEEj/dxyYJ6Zc6AiSeaBY8dWOa11GF/ppQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.50.0.tgz", - "integrity": "sha512-I1gSMzkVe1KzAxKAroCJL30hA4DqSi+wGc5gviD0y3IL/VkvcnAqwBf4RHXHyvH66YVHxpKO8ojrgc4SrWAnLg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.50.0.tgz", - "integrity": "sha512-bSbWlY3jZo7molh4tc5dKfeSxkqnf48UsLqYbUhnkdnfgZjgufLS/NTA8PcP/dnvct5CCdNkABJ56CbclMRYCA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.50.0.tgz", - "integrity": "sha512-LSXSGumSURzEQLT2e4sFqFOv3LWZsEF8FK7AAv9zHZNDdMnUPYH3t8ZlaeYYZyTXnsob3htwTKeWtBIkPV27iQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.50.0.tgz", - "integrity": "sha512-CxRKyakfDrsLXiCyucVfVWVoaPA4oFSpPpDwlMcDFQvrv3XY6KEzMtMZrA+e/goC8xxp2WSOxHQubP8fPmmjOQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.0.tgz", - "integrity": "sha512-8PrJJA7/VU8ToHVEPu14FzuSAqVKyo5gg/J8xUerMbyNkWkO9j2ExBho/68RnJsMGNJq4zH114iAttgm7BZVkA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.0.tgz", - "integrity": "sha512-SkE6YQp+CzpyOrbw7Oc4MgXFvTw2UIBElvAvLCo230pyxOLmYwRPwZ/L5lBe/VW/qT1ZgND9wJfOsdy0XptRvw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.50.0.tgz", - "integrity": "sha512-PZkNLPfvXeIOgJWA804zjSFH7fARBBCpCXxgkGDRjjAhRLOR8o0IGS01ykh5GYfod4c2yiiREuDM8iZ+pVsT+Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.50.0.tgz", - "integrity": "sha512-q7cIIdFvWQoaCbLDUyUc8YfR3Jh2xx3unO8Dn6/TTogKjfwrax9SyfmGGK6cQhKtjePI7jRfd7iRYcxYs93esg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.50.0.tgz", - "integrity": "sha512-XzNOVg/YnDOmFdDKcxxK410PrcbcqZkBmz+0FicpW5jtjKQxcW1BZJEQOF0NJa6JO7CZhett8GEtRN/wYLYJuw==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.0.tgz", - "integrity": "sha512-xMmiWRR8sp72Zqwjgtf3QbZfF1wdh8X2ABu3EaozvZcyHJeU0r+XAnXdKgs4cCAp6ORoYoCygipYP1mjmbjrsg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@shikijs/core": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.12.2.tgz", - "integrity": "sha512-L1Safnhra3tX/oJK5kYHaWmLEBJi1irASwewzY3taX5ibyXyMkkSDZlq01qigjryOBwrXSdFgTiZ3ryzSNeu7Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/types": "3.12.2", - "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4", - "hast-util-to-html": "^9.0.5" - } - }, - "node_modules/@shikijs/engine-javascript": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.12.2.tgz", - "integrity": "sha512-Nm3/azSsaVS7hk6EwtHEnTythjQfwvrO5tKqMlaH9TwG1P+PNaR8M0EAKZ+GaH2DFwvcr4iSfTveyxMIvXEHMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/types": "3.12.2", - "@shikijs/vscode-textmate": "^10.0.2", - "oniguruma-to-es": "^4.3.3" - } - }, - "node_modules/@shikijs/engine-oniguruma": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.12.2.tgz", - "integrity": "sha512-hozwnFHsLvujK4/CPVHNo3Bcg2EsnG8krI/ZQ2FlBlCRpPZW4XAEQmEwqegJsypsTAN9ehu2tEYe30lYKSZW/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/types": "3.12.2", - "@shikijs/vscode-textmate": "^10.0.2" - } - }, - "node_modules/@shikijs/langs": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.12.2.tgz", - "integrity": "sha512-bVx5PfuZHDSHoBal+KzJZGheFuyH4qwwcwG/n+MsWno5cTlKmaNtTsGzJpHYQ8YPbB5BdEdKU1rga5/6JGY8ww==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/types": "3.12.2" - } - }, - "node_modules/@shikijs/themes": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.12.2.tgz", - "integrity": "sha512-fTR3QAgnwYpfGczpIbzPjlRnxyONJOerguQv1iwpyQZ9QXX4qy/XFQqXlf17XTsorxnHoJGbH/LXBvwtqDsF5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/types": "3.12.2" - } - }, - "node_modules/@shikijs/transformers": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-3.12.2.tgz", - "integrity": "sha512-+z1aMq4N5RoNGY8i7qnTYmG2MBYzFmwkm/yOd6cjEI7OVzcldVvzQCfxU1YbIVgsyB0xHVc2jFe1JhgoXyUoSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/core": "3.12.2", - "@shikijs/types": "3.12.2" - } - }, - "node_modules/@shikijs/types": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.12.2.tgz", - "integrity": "sha512-K5UIBzxCyv0YoxN3LMrKB9zuhp1bV+LgewxuVwHdl4Gz5oePoUFrr9EfgJlGlDeXCU1b/yhdnXeuRvAnz8HN8Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" - } - }, - "node_modules/@shikijs/vscode-textmate": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", - "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/markdown-it": { - "version": "14.1.2", - "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", - "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/linkify-it": "^5", - "@types/mdurl": "^2" - } - }, - "node_modules/@types/mdast": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/mdurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "24.3.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.1.tgz", - "integrity": "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~7.10.0" - } - }, - "node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/web-bluetooth": { - "version": "0.0.21", - "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", - "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", - "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", - "dev": true, - "license": "ISC" - }, - "node_modules/@vitejs/plugin-vue": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.1.tgz", - "integrity": "sha512-+MaE752hU0wfPFJEUAIxqw18+20euHHdxVtMvbFcOEpjEyfqXH/5DCoTHiVJ0J29EhTJdoTkjEv5YBKU9dnoTw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rolldown/pluginutils": "1.0.0-beta.29" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "peerDependencies": { - "vite": "^5.0.0 || ^6.0.0 || ^7.0.0", - "vue": "^3.2.25" - } - }, - "node_modules/@vue/compiler-core": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.21.tgz", - "integrity": "sha512-8i+LZ0vf6ZgII5Z9XmUvrCyEzocvWT+TeR2VBUVlzIH6Tyv57E20mPZ1bCS+tbejgUgmjrEh7q/0F0bibskAmw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.28.3", - "@vue/shared": "3.5.21", - "entities": "^4.5.0", - "estree-walker": "^2.0.2", - "source-map-js": "^1.2.1" - } - }, - "node_modules/@vue/compiler-dom": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.21.tgz", - "integrity": "sha512-jNtbu/u97wiyEBJlJ9kmdw7tAr5Vy0Aj5CgQmo+6pxWNQhXZDPsRr1UWPN4v3Zf82s2H3kF51IbzZ4jMWAgPlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/compiler-core": "3.5.21", - "@vue/shared": "3.5.21" - } - }, - "node_modules/@vue/compiler-sfc": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.21.tgz", - "integrity": "sha512-SXlyk6I5eUGBd2v8Ie7tF6ADHE9kCR6mBEuPyH1nUZ0h6Xx6nZI29i12sJKQmzbDyr2tUHMhhTt51Z6blbkTTQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.28.3", - "@vue/compiler-core": "3.5.21", - "@vue/compiler-dom": "3.5.21", - "@vue/compiler-ssr": "3.5.21", - "@vue/shared": "3.5.21", - "estree-walker": "^2.0.2", - "magic-string": "^0.30.18", - "postcss": "^8.5.6", - "source-map-js": "^1.2.1" - } - }, - "node_modules/@vue/compiler-ssr": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.21.tgz", - "integrity": "sha512-vKQ5olH5edFZdf5ZrlEgSO1j1DMA4u23TVK5XR1uMhvwnYvVdDF0nHXJUblL/GvzlShQbjhZZ2uvYmDlAbgo9w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/compiler-dom": "3.5.21", - "@vue/shared": "3.5.21" - } - }, - "node_modules/@vue/devtools-api": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-8.0.1.tgz", - "integrity": "sha512-YBvjfpM7LEp5+b7ZDm4+mFrC+TgGjUmN8ff9lZcbHQ1MKhmftT/urCTZP0y1j26YQWr25l9TPaEbNLbILRiGoQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/devtools-kit": "^8.0.1" - } - }, - "node_modules/@vue/devtools-kit": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-8.0.1.tgz", - "integrity": "sha512-7kiPhgTKNtNeXltEHnJJjIDlndlJP4P+UJvCw54uVHNDlI6JzwrSiRmW4cxKTug2wDbc/dkGaMnlZghcwV+aWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/devtools-shared": "^8.0.1", - "birpc": "^2.5.0", - "hookable": "^5.5.3", - "mitt": "^3.0.1", - "perfect-debounce": "^1.0.0", - "speakingurl": "^14.0.1", - "superjson": "^2.2.2" - } - }, - "node_modules/@vue/devtools-shared": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-8.0.1.tgz", - "integrity": "sha512-PqtWqPPRpMwZ9FjTzyugb5KeV9kmg2C3hjxZHwjl0lijT4QIJDd0z6AWcnbM9w2nayjDymyTt0+sbdTv3pVeNg==", - "dev": true, - "license": "MIT", - "dependencies": { - "rfdc": "^1.4.1" - } - }, - "node_modules/@vue/reactivity": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.21.tgz", - "integrity": "sha512-3ah7sa+Cwr9iiYEERt9JfZKPw4A2UlbY8RbbnH2mGCE8NwHkhmlZt2VsH0oDA3P08X3jJd29ohBDtX+TbD9AsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/shared": "3.5.21" - } - }, - "node_modules/@vue/runtime-core": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.21.tgz", - "integrity": "sha512-+DplQlRS4MXfIf9gfD1BOJpk5RSyGgGXD/R+cumhe8jdjUcq/qlxDawQlSI8hCKupBlvM+3eS1se5xW+SuNAwA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/reactivity": "3.5.21", - "@vue/shared": "3.5.21" - } - }, - "node_modules/@vue/runtime-dom": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.21.tgz", - "integrity": "sha512-3M2DZsOFwM5qI15wrMmNF5RJe1+ARijt2HM3TbzBbPSuBHOQpoidE+Pa+XEaVN+czbHf81ETRoG1ltztP2em8w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/reactivity": "3.5.21", - "@vue/runtime-core": "3.5.21", - "@vue/shared": "3.5.21", - "csstype": "^3.1.3" - } - }, - "node_modules/@vue/server-renderer": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.21.tgz", - "integrity": "sha512-qr8AqgD3DJPJcGvLcJKQo2tAc8OnXRcfxhOJCPF+fcfn5bBGz7VCcO7t+qETOPxpWK1mgysXvVT/j+xWaHeMWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/compiler-ssr": "3.5.21", - "@vue/shared": "3.5.21" - }, - "peerDependencies": { - "vue": "3.5.21" - } - }, - "node_modules/@vue/shared": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.21.tgz", - "integrity": "sha512-+2k1EQpnYuVuu3N7atWyG3/xoFWIVJZq4Mz8XNOdScFI0etES75fbny/oU4lKWk/577P1zmg0ioYvpGEDZ3DLw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@vueuse/core": { - "version": "13.9.0", - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-13.9.0.tgz", - "integrity": "sha512-ts3regBQyURfCE2BcytLqzm8+MmLlo5Ln/KLoxDVcsZ2gzIwVNnQpQOL/UKV8alUqjSZOlpFZcRNsLRqj+OzyA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/web-bluetooth": "^0.0.21", - "@vueuse/metadata": "13.9.0", - "@vueuse/shared": "13.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "vue": "^3.5.0" - } - }, - "node_modules/@vueuse/integrations": { - "version": "13.9.0", - "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-13.9.0.tgz", - "integrity": "sha512-SDobKBbPIOe0cVL7QxMzGkuUGHvWTdihi9zOrrWaWUgFKe15cwEcwfWmgrcNzjT6kHnNmWuTajPHoIzUjYNYYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vueuse/core": "13.9.0", - "@vueuse/shared": "13.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "async-validator": "^4", - "axios": "^1", - "change-case": "^5", - "drauu": "^0.4", - "focus-trap": "^7", - "fuse.js": "^7", - "idb-keyval": "^6", - "jwt-decode": "^4", - "nprogress": "^0.2", - "qrcode": "^1.5", - "sortablejs": "^1", - "universal-cookie": "^7 || ^8", - "vue": "^3.5.0" - }, - "peerDependenciesMeta": { - "async-validator": { - "optional": true - }, - "axios": { - "optional": true - }, - "change-case": { - "optional": true - }, - "drauu": { - "optional": true - }, - "focus-trap": { - "optional": true - }, - "fuse.js": { - "optional": true - }, - "idb-keyval": { - "optional": true - }, - "jwt-decode": { - "optional": true - }, - "nprogress": { - "optional": true - }, - "qrcode": { - "optional": true - }, - "sortablejs": { - "optional": true - }, - "universal-cookie": { - "optional": true - } - } - }, - "node_modules/@vueuse/metadata": { - "version": "13.9.0", - "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-13.9.0.tgz", - "integrity": "sha512-1AFRvuiGphfF7yWixZa0KwjYH8ulyjDCC0aFgrGRz8+P4kvDFSdXLVfTk5xAN9wEuD1J6z4/myMoYbnHoX07zg==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/@vueuse/shared": { - "version": "13.9.0", - "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-13.9.0.tgz", - "integrity": "sha512-e89uuTLMh0U5cZ9iDpEI2senqPGfbPRTHM/0AaQkcxnpqjkZqDYP8rpfm7edOz8s+pOCOROEy1PIveSW8+fL5g==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "vue": "^3.5.0" - } - }, - "node_modules/birpc": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.5.0.tgz", - "integrity": "sha512-VSWO/W6nNQdyP520F1mhf+Lc2f8pjGQOtoHHm7Ze8Go1kX7akpVIrtTa0fn+HB0QJEDVacl6aO08YE0PgXfdnQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/ccount": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", - "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-html4": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", - "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-legacy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", - "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/comma-separated-tokens": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", - "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/copy-anything": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz", - "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-what": "^4.1.8" - }, - "engines": { - "node": ">=12.13" - }, - "funding": { - "url": "https://github.com/sponsors/mesqueeb" - } - }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true, - "license": "MIT" - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/devlop": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", - "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", - "dev": true, - "license": "MIT", - "dependencies": { - "dequal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/esbuild": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", - "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.9", - "@esbuild/android-arm": "0.25.9", - "@esbuild/android-arm64": "0.25.9", - "@esbuild/android-x64": "0.25.9", - "@esbuild/darwin-arm64": "0.25.9", - "@esbuild/darwin-x64": "0.25.9", - "@esbuild/freebsd-arm64": "0.25.9", - "@esbuild/freebsd-x64": "0.25.9", - "@esbuild/linux-arm": "0.25.9", - "@esbuild/linux-arm64": "0.25.9", - "@esbuild/linux-ia32": "0.25.9", - "@esbuild/linux-loong64": "0.25.9", - "@esbuild/linux-mips64el": "0.25.9", - "@esbuild/linux-ppc64": "0.25.9", - "@esbuild/linux-riscv64": "0.25.9", - "@esbuild/linux-s390x": "0.25.9", - "@esbuild/linux-x64": "0.25.9", - "@esbuild/netbsd-arm64": "0.25.9", - "@esbuild/netbsd-x64": "0.25.9", - "@esbuild/openbsd-arm64": "0.25.9", - "@esbuild/openbsd-x64": "0.25.9", - "@esbuild/openharmony-arm64": "0.25.9", - "@esbuild/sunos-x64": "0.25.9", - "@esbuild/win32-arm64": "0.25.9", - "@esbuild/win32-ia32": "0.25.9", - "@esbuild/win32-x64": "0.25.9" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true, - "license": "MIT" - }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/focus-trap": { - "version": "7.6.5", - "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.6.5.tgz", - "integrity": "sha512-7Ke1jyybbbPZyZXFxEftUtxFGLMpE2n6A+z//m4CRDlj0hW+o3iYSmh8nFlYMurOiJVDmJRilUQtJr08KfIxlg==", - "dev": true, - "license": "MIT", - "dependencies": { - "tabbable": "^6.2.0" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/hast-util-to-html": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", - "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "ccount": "^2.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-whitespace": "^3.0.0", - "html-void-elements": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "property-information": "^7.0.0", - "space-separated-tokens": "^2.0.0", - "stringify-entities": "^4.0.0", - "zwitch": "^2.0.4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-whitespace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", - "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hookable": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", - "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/html-void-elements": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", - "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-what": { - "version": "4.1.16", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz", - "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.13" - }, - "funding": { - "url": "https://github.com/sponsors/mesqueeb" - } - }, - "node_modules/magic-string": { - "version": "0.30.18", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.18.tgz", - "integrity": "sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/mark.js": { - "version": "8.11.1", - "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz", - "integrity": "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/mdast-util-to-hast": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", - "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@ungap/structured-clone": "^1.0.0", - "devlop": "^1.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "trim-lines": "^3.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-util-character": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", - "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-encode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", - "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-sanitize-uri": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", - "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-symbol": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", - "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-types": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", - "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/minisearch": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-7.1.2.tgz", - "integrity": "sha512-R1Pd9eF+MD5JYDDSPAp/q1ougKglm14uEkPMvQ/05RGmx6G9wvmLTrTI/Q5iPNJLYqNdsDQ7qTGIcNWR+FrHmA==", - "dev": true, - "license": "MIT" - }, - "node_modules/mitt": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", - "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", - "dev": true, - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/oniguruma-parser": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.1.tgz", - "integrity": "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==", - "dev": true, - "license": "MIT" - }, - "node_modules/oniguruma-to-es": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.3.tgz", - "integrity": "sha512-rPiZhzC3wXwE59YQMRDodUwwT9FZ9nNBwQQfsd1wfdtlKEyCdRV0avrTcSZ5xlIvGRVPd/cx6ZN45ECmS39xvg==", - "dev": true, - "license": "MIT", - "dependencies": { - "oniguruma-parser": "^0.12.1", - "regex": "^6.0.1", - "regex-recursion": "^6.0.2" - } - }, - "node_modules/perfect-debounce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", - "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", - "dev": true, - "license": "MIT" - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/property-information": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", - "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/regex/-/regex-6.0.1.tgz", - "integrity": "sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==", - "dev": true, - "license": "MIT", - "dependencies": { - "regex-utilities": "^2.3.0" - } - }, - "node_modules/regex-recursion": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", - "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", - "dev": true, - "license": "MIT", - "dependencies": { - "regex-utilities": "^2.3.0" - } - }, - "node_modules/regex-utilities": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", - "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", - "dev": true, - "license": "MIT" - }, - "node_modules/rfdc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", - "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "dev": true, - "license": "MIT" - }, - "node_modules/rollup": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.50.0.tgz", - "integrity": "sha512-/Zl4D8zPifNmyGzJS+3kVoyXeDeT/GrsJM94sACNg9RtUE0hrHa1bNPtRSrfHTMH5HjRzce6K7rlTh3Khiw+pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.50.0", - "@rollup/rollup-android-arm64": "4.50.0", - "@rollup/rollup-darwin-arm64": "4.50.0", - "@rollup/rollup-darwin-x64": "4.50.0", - "@rollup/rollup-freebsd-arm64": "4.50.0", - "@rollup/rollup-freebsd-x64": "4.50.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.50.0", - "@rollup/rollup-linux-arm-musleabihf": "4.50.0", - "@rollup/rollup-linux-arm64-gnu": "4.50.0", - "@rollup/rollup-linux-arm64-musl": "4.50.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.50.0", - "@rollup/rollup-linux-ppc64-gnu": "4.50.0", - "@rollup/rollup-linux-riscv64-gnu": "4.50.0", - "@rollup/rollup-linux-riscv64-musl": "4.50.0", - "@rollup/rollup-linux-s390x-gnu": "4.50.0", - "@rollup/rollup-linux-x64-gnu": "4.50.0", - "@rollup/rollup-linux-x64-musl": "4.50.0", - "@rollup/rollup-openharmony-arm64": "4.50.0", - "@rollup/rollup-win32-arm64-msvc": "4.50.0", - "@rollup/rollup-win32-ia32-msvc": "4.50.0", - "@rollup/rollup-win32-x64-msvc": "4.50.0", - "fsevents": "~2.3.2" - } - }, - "node_modules/shiki": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.12.2.tgz", - "integrity": "sha512-uIrKI+f9IPz1zDT+GMz+0RjzKJiijVr6WDWm9Pe3NNY6QigKCfifCEv9v9R2mDASKKjzjQ2QpFLcxaR3iHSnMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/core": "3.12.2", - "@shikijs/engine-javascript": "3.12.2", - "@shikijs/engine-oniguruma": "3.12.2", - "@shikijs/langs": "3.12.2", - "@shikijs/themes": "3.12.2", - "@shikijs/types": "3.12.2", - "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/space-separated-tokens": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/speakingurl": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", - "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stringify-entities": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", - "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", - "dev": true, - "license": "MIT", - "dependencies": { - "character-entities-html4": "^2.0.0", - "character-entities-legacy": "^3.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/superjson": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.2.tgz", - "integrity": "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "copy-anything": "^3.0.2" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/tabbable": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", - "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/trim-lines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", - "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/undici-types": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", - "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==", - "dev": true, - "license": "MIT" - }, - "node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-position": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", - "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", - "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-message": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", - "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vite": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.5.tgz", - "integrity": "sha512-4cKBO9wR75r0BeIWWWId9XK9Lj6La5X846Zw9dFfzMRw38IlTk2iCcUt6hsyiDRcPidc55ZParFYDXi0nXOeLQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.25.0", - "fdir": "^6.5.0", - "picomatch": "^4.0.3", - "postcss": "^8.5.6", - "rollup": "^4.43.0", - "tinyglobby": "^0.2.15" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^20.19.0 || >=22.12.0", - "jiti": ">=1.21.0", - "less": "^4.0.0", - "lightningcss": "^1.21.0", - "sass": "^1.70.0", - "sass-embedded": "^1.70.0", - "stylus": ">=0.54.8", - "sugarss": "^5.0.0", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/vitepress": { - "version": "2.0.0-alpha.12", - "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-2.0.0-alpha.12.tgz", - "integrity": "sha512-yZwCwRRepcpN5QeAhwSnEJxS3I6zJcVixqL1dnm6km4cnriLpQyy2sXQDsE5Ti3pxGPbhU51nTMwI+XC1KNnJg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@docsearch/css": "^4.0.0-beta.7", - "@docsearch/js": "^4.0.0-beta.7", - "@iconify-json/simple-icons": "^1.2.47", - "@shikijs/core": "^3.9.2", - "@shikijs/transformers": "^3.9.2", - "@shikijs/types": "^3.9.2", - "@types/markdown-it": "^14.1.2", - "@vitejs/plugin-vue": "^6.0.1", - "@vue/devtools-api": "^8.0.0", - "@vue/shared": "^3.5.18", - "@vueuse/core": "^13.6.0", - "@vueuse/integrations": "^13.6.0", - "focus-trap": "^7.6.5", - "mark.js": "8.11.1", - "minisearch": "^7.1.2", - "shiki": "^3.9.2", - "vite": "^7.1.2", - "vue": "^3.5.18" - }, - "bin": { - "vitepress": "bin/vitepress.js" - }, - "peerDependencies": { - "markdown-it-mathjax3": "^4", - "oxc-minify": "^0.82.1", - "postcss": "^8" - }, - "peerDependenciesMeta": { - "markdown-it-mathjax3": { - "optional": true - }, - "oxc-minify": { - "optional": true - }, - "postcss": { - "optional": true - } - } - }, - "node_modules/vue": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.21.tgz", - "integrity": "sha512-xxf9rum9KtOdwdRkiApWL+9hZEMWE90FHh8yS1+KJAiWYh+iGWV1FquPjoO9VUHQ+VIhsCXNNyZ5Sf4++RVZBA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/compiler-dom": "3.5.21", - "@vue/compiler-sfc": "3.5.21", - "@vue/runtime-dom": "3.5.21", - "@vue/server-renderer": "3.5.21", - "@vue/shared": "3.5.21" - }, - "peerDependencies": { - "typescript": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/zwitch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", - "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - } - } -} diff --git a/docs/package.json b/docs/package.json deleted file mode 100644 index 62ddf81..0000000 --- a/docs/package.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "webrtc-java-docs", - "scripts": { - "dev": "vitepress dev", - "build": "vitepress build", - "preview": "vitepress preview" - }, - "devDependencies": { - "@types/node": "^24.3.1", - "vitepress": "^2.0.0-alpha.12" - } -} diff --git a/docs/public/apple-touch-icon.png b/docs/public/apple-touch-icon.png deleted file mode 100644 index d48cf0eb499c9d5181340e2df2377a0b38769c7a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10117 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 diff --git a/docs/public/favicon-96x96.png b/docs/public/favicon-96x96.png deleted file mode 100644 index 9b043bd22b90a4af8d9e25dbdd91f0f5334a8d98..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5478 zcmV-s6`AUZP)^`L(&yuI>YyHDdw4a%vjLq&_Dv+fMHfB6ljfjore12k z2&u?XG=|jVO*Wfy(b!Qhlu~J8{AVfEia_BPF69fsktgYlQ1WbB z=>+F$-Nx9$eu*OShx3ZABXq;4UQt;^cX5? zi>qtkD6;1kOLH4~+Tt*h@SFPvf+Tj^grDT3SEbe<7e#GhBPtcXBaQr@29M(Nlf;RK z(LIlsi&?8$vYO`d;4q8WQHDsAxec_V4H@rSo#zpndmf?bMs=KPimymqWi{xKSvq5B z(wY)zfkq%z8=OxHaT29!FGD#MH;1IVxXL;*(-fy8oS*I()ScvB8|SG#pPK(%Q4Qe& z8U4rcc*zyjUP)N&DA>JbjOy-cu5O3dQ)Nr1CQ4pgf3L?gE2$zj7gZ6PtJ_L?R(6)` z)-zxB88|==K6)q$P8fk>PZ=eTKjTz+(mAJN)aWxY>fAGN(m7|~gfmZ-M~^&S`m(ct zOyf~I7kc0->ls06rj9#+e)nGa^7zwFk(W-sQcnKuZJ2!5t+?hlH)G;$H)6uA*JJ!G zlWD@QCZq5sh1a6+<`9m*d`YFox65HPF^l7pO1tkK>SuiL=b$(T0V;c zjR61>&50qZ13s$A$3~z9p``|i%;I2h0AW^6jvO}P80Y4xcRAPJbB7o->_|=`m`t#a z;hA}eD^pcf6{MnNQUh+P*&)yrV1g8TC1xi>Wg?kOv-qjK$slYyCod1DU2v|v;?^lN zxZp@ZNfJ*;S3{`UTM66YElLYA|f&F{-LE1`N38jWomy0T8li8S= zu>t&xzJMxjMktW64Rt4b#E{b|PhNP%<@V??7m<(8a%e!6PD2inq#6<>Y}oRFWor&ZA_N-OZnGt=?=+aJVZ z_dJTv|2Yq}HMMc_N;;NQy}v4W1Odu?hNx169z0mwdcM%=$botIAj^`ue9m{v?;(2~ zewgetpr1VU$@Y*@D$0e+ZQ*VN;)j~8Ixhx5_c z(3q&?qU_whQ~K-t)FS!ATxKJO1UVpPw;^WbWXpbo2g;GBk8;i*dy%~2rmN)*cioKZ z8LzwJMojwkbu{VL$rv+fJmq!HBUil=rVhV8E}p*(HFf-9%9jI#(S{EzSFAx*RZW6U zgdlmcWkWGqE`Jz7m^iky8e63M#C1x7J$m(&6K=f9nfBBp^7aSsB%X`Wmz_r^o^}!) zHGCKiJaRDg9n_Ed^gA5A`t+u}E}ht@De@5A@2|(c{aj>UHV}t(^)~kMJAOzq@vr3O zZCY1MvH1(ct||3(b9R7$Q_UU#u%lK$3ft^IWRSdL+HWxOw2>kwH=DCWQlO*~Ku%6J zI(P2|_?qti$UM7KXLRk>#b{;Csx@|Pbsf9mD;#G?*u7479{ImiTI1m!`?bR4-E zs&K7@xt;Pb^q2z5$<@C`YJ)Nm9oxaqAAUqx$#(2>o$VwD#||HiyYIRJx7|7hci%Z4 zQ?9)L`T2Y_v8}k;BM=B+`Ijry_n!dkf>S? zd4c@iJ>?MvLpb`(ua(Q!;(w;UhnHS>3vbT&02SrCLPlk1$ji+}|GvF&Xzv~z9>*CX zqiGf*RFrIYHm%!CP`Q8rH6}$au0e(*f-FpfUJ`JiMTR-{(J>vjn^M z`_bU|u&rzl7Js?QOGV3TY;44`#mljG&pt{e-&ACxHPLzu5seK9vWZpz1f+>FiM+5Z zoN)5-L9?~|qW7w67?^Ml-%{yaT*)$-NKIlMqJQ(Dp;Rs^BPl#K>bb@loiEMhJ4UvoLz}N$8rN z50Tp$efsvnslON=VkZ2RF%*s-dw1`1K6-Di^Wi@}wYc~cABTR;X41-=ch&`{s#EdKoKz`E6&a^h`w>e5AyI{ifQX}@ZaAjHBiMh?Z4 zE6>4=*NnzB6VAlI{=HoS@zTtajC}2=*vU7*`*P{x6+(gtDd$2+U6yNPe$;w!0Ave$ zGY7^^P!3%P*PPOuckR*58FJJ>v3|{_2L7tRXFE0_&PM-1edQ6u1``8Ek$A~Cl4S|> zJ^TR;}Js#)AsV6{#oyQWbuz4R@7!#M+ghYpFBe5 z=H)8G(1DSm6ON@+57t z-UZP%C?h(w*o2OrKqFXLKIC=k)G+(qPpq1nx-6Yd;q%GCM-D_3C^}0zNxavaRMc0~ z>(>_BZ_k*8uNJKk0h@PTLX0XGz9+PF#Y>Lr6MiT!4qVw$^=S$tVa65{XfcF};s;9| zDgOYl!HiHKD?2-|deu7Y+_78zYbPMVo&fI(nm_kTX$OKo#v}%g1p+oa<4=f36Q@Zg zoCi@@$33c@06nDC09KWaa2}FUzR3wRfLN_1P(7S9cKme>KYsPaH-B;*`7Zm;_^PR{ zMQyEmj3tTN5D(mR_goXZ)X>lZ4Zx1#qMeOo-77(Fa1+p4$o9(^r|c@Ncs#dL_AT7> z50D{LR@H)^IcTkz^>$UWDdZDoU@0>*p7X<|2X>WieBegu;6DH=XHs=tgLw2M_acR`6r%F`*;7i_qTlae#?!32^?E@RE4CK-u}Invd-VY zgyzMEG;(Q@1%ulkFEv+M4G8IzEZx-bG(VWfOW;KiZDm9dL7`DKA~mc5(U+|B1lcGo z-B3TZqM|6~7xSl{c;)2RU!9e=Yv&#taZp)V<9z?!27C4Q8yn+T(WT=!*j}+qt%-f1 zeb8KHGY4K!y=Wm3}Z0DZ>j2eC;ngnE#Rm2l`uIM&#Jg{w=~`yVMO z{vChsR1|;<`WHNYy#xC5mM!JO{{Hr->KNgAI zKO6R+rvtucNll z%Mpmswg^Q12^hhHWz;b;)VaNV!+ncNH{A1l+1h)jmaf0=w$iot-d?)y-Umw8GHuiE z=I`5Dw9jZD%s6bs9}l%Gx}S(The^R<*RH+3-9PT*TPwJX{>jP7iPAiX%f>@y7k_#`FFIxknjj(>E zd~(_0ou25gwT>XP2Aor5Nm$o{s2d}U2re=aNLWt6(L)F^AcL#oO=Zr`U3)DMvs)4Q zn1!bguz%=*Z!bNgy{Lz6@7$jRork0a6X@Bihh12BZXiFu8~-8`8*yEoUoKw!ErFPx z)D{c1ri|LH9ER@da1F@G%DxUH@)%)4%ja`WJh7l*;=~K&$WcdU3H9{=nqc?tN@vcT zrE<&G9|&Xt#A&91l!k0dw!!|P2Qx=6-}+QRSAz&9?A7a##>v-S6c{`9?5qI;`}jn- z`uw^nH*c=6-+5000FKNkl zHfQwy`Ez{$F%%%cg+!M60pB_8)Z_d&+;|!F>)$7Lz!$PRv)8f(XG(`zn~Ob-kp86=fea^^CdIcR&x$#x1jAA;-dB4Nqy zJ-P%63I+r^cgf3MuwbQl>+QMnyNneR{~U1TW_uUeoNNec`In?^7Ue4afR5ur%LcwK-?@&Ax zql)t@;?^7!F$R5udC-HIqnB@0Dv^^9Qpv?)W55oc=c*Yxe%ds|+K0wx+B78EjJ}?F zRM~^osVi0lbc)n{bU2|kGPuUJqjO{>q2$SV2 zK?a3uJ6%3FRGg}?YD|VO16wjP+nU2~l4~W@KZWG5(%Iskvgv;khNnFho4WJWm_djGM!ZT%5EZdyaohgbiU@qKL&p{!HAYaPFEE(T?7|6T^+alfpi3c zp?v9--IC}jK6CklnJQXKVH&TbNj`NWg|nX`GRhX`rMoyY9l8B!WnWENYCCirKn^Iw zJ20vbq-+byCxED~T6-W8d3+Ov_045AbI|@!@%7bjf#?xN^*=VjV-vQ+13AV&#TDEu z9+;s+H$a8$^NVNrdGHrN)FQH_)u_%@HKu@klp&;>#u1c)-H=T#VKP||Ou*VER>z=k zUNLch*Td;iThcTs;UJidN+?Z~N*)YqY-9AOvImP}?I72hcP2KJFTUbwY0;&;8&-j+ zkr8QO!V$r#6E~tQQ0-RefuqnfIwG}f!Gwn^DHxYDS*&U+u+3)Y3IX4=WmJGfAS-SMPt< zByd1Bz?FA#kc&qHD!*RPb(xb<1K)i3s6EkRFiS#r$|ld}W8 z0nxn5=Z`NdnO``gv}(ZJHaSy-?TjT!1)-T6Z%$Z-_$w~5yyP&cG({!~ z0p8_kd+xyow0+HEJRWR7OgY+qaj*exU-KA`2OAJmj>JW4Q~nPC0RR6SJad@<000I_ cL_t&o03i-!8!v|GZ~y=R07*qoM6N<$f^=DhzyJUM diff --git a/docs/public/favicon.ico b/docs/public/favicon.ico deleted file mode 100644 index bec53e9c165f2bbb82a9a80db68753d79b0d877c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15086 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 USbwl%%)tG}hBtuE0u1N(zruHS2LJ#7 diff --git a/docs/public/favicon.svg b/docs/public/favicon.svg deleted file mode 100644 index aeb21ad..0000000 --- a/docs/public/favicon.svg +++ /dev/null @@ -1,3 +0,0 @@ - \ No newline at end of file diff --git a/docs/public/logo.png b/docs/public/logo.png deleted file mode 100644 index 7e86ad46bf1161b1b796cb88730b3aac448fa2e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36847 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 T0SoV7BO;#5Kg)fp|Ka}tB<*eo diff --git a/docs/public/site.webmanifest b/docs/public/site.webmanifest deleted file mode 100644 index 6b8bf46..0000000 --- a/docs/public/site.webmanifest +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "JRTC", - "short_name": "JRTC", - "icons": [ - { - "src": "/web-app-manifest-192x192.png", - "sizes": "192x192", - "type": "image/png", - "purpose": "maskable" - }, - { - "src": "/web-app-manifest-512x512.png", - "sizes": "512x512", - "type": "image/png", - "purpose": "maskable" - } - ], - "theme_color": "#1e0959", - "background_color": "#1e0959", - "display": "standalone" -} \ No newline at end of file diff --git a/docs/public/web-app-manifest-192x192.png b/docs/public/web-app-manifest-192x192.png deleted file mode 100644 index acf34436792fababbcb715698d32bfcfe862c3e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8989 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¬u)N9TTIs0!pIu3 zoB(zz+gK9!Y5Dg}BGY5sn=#6=tHGexz{%=nI}~2}x4X z)18bsA}*FJbGH?vY=yQ(;{?zavw~vzJj`F2l%Oj+(T!!-fr;UyLjko>pT18RzI!-! zAaaiNNu?bE`5X-SHA*L^$5uxrW0U0)=vI2j6+zBZ&5}2YFPTRXgCqfp!0@%p;8&R} zyNE{;f&{r8g%$h=za$CZf~kbIWfQIf89nU)r$VrEd~zNb!T?&9BmrF9;yC5(*a?{b z#ga@UQxd{ZypO~J;TB;Z2FDl^z%i7j^!}*i3-1ebK)UkpCMXe_J%}!1624{2c}Y;J05G?I~8bElGedJi@2Ks(lNL?!Dy3 z5mrW7Ckm-fIq{Kzb*hiOj?hH1nRCy;oRb6y4Bd#1@|UK!EeGT;PfPH{K!%eH32>+S zxa&s1rOTmh0;mWyjDlwbY6fG;>5uB^fU#v6V7@9X){Z5TP;#<27_9ESM5cQyyB4Cg zWnF0(7E6|eg%azkiaTowyG(`l%72+z56J%t##q( zui93^{D57*r6XK z2@s`EdCdKjzz0?0q>6Il+Ux#OyiLqC+Qj^X1~w%D#A(E<&%sxp<7yfC+75sV${ zVDQRNzJTSG!fU{KYDY(TYA15pHlmH(19MIiATV@(I`WPymx0>26zc8gfsP#*OK*@W znqRQj4`$xm3VZLZhqp`;U^pHT9??yl5}~`DQ=%m>*1W(c$GgEx0;=bVz_Hlsijd1e zWqYAxi7^3mG`|cwF$t8c67AUrwcWBuy@uM+Yrmjv}brsZxSD6rtVaUD1 z>KA|wuK`<^0c}hc`F#YrV#o?pH*c<`UvD=I`K5g!Nvuo{5G7HLv2U;WyAj5kmw;_6 zpftVtCB)_yPXcg2Fr|&vk1*^u?-{ZTs6NPBr`X#H@VSE8%mmoL>C(Et@ruEuko$?Z z7c)^70n48OmMtX7H)%PiSCP^)g&TY7qV_OpIRygZoYBK~i6;T{#=tjdt{q}ccnXu` zkhf3eUV>8($Y{^e7@R7pzI{Mn7tq_utH~hosv=LO!=_%!hODx_0008INklWm z>~jT4j|TB1fF8ESr-k+juf2ki`l{Ia=n{YfQ>0cT%o79xB2XNf(Ir4}ngvvJtaWpQ ztk`Q~4Hz%>2E-@21n{DC(qjMj%Om(U@p=#*BT(fHqrbr*|bN6iEU&`l=F8sW=@I z#Dlslk^~qv9*sH?RNbUsDF{?gnuHfnkt9IDNkyOKLVgrZqfQhlS^c}!V|{o56;A?` zE4D`AH0ngTG)v@afX(YUqoA#tBe87i?Ge7n@qV@7l528$=I=#tBf`bfvW3 zF$Y$$vc>x`tD&E`=)ur90ZMa+m$4%aUbNiZY^}6!c) zajO}Lybu#068#dU2?CKKkR(8)@FvW4M<7W6-941(7bybaCcs#pOh)Ragn3j5gqr{X z@5G}rF5z1N2sjR!_LX6UTDS>N0eDBEqAOE-N4j>c_6ClTY+vb)sCx^6Hdq39<1PFX zG7+$Mq*H{Om$1!CbN@dEL8)VRVbeP9)ZWtD=zZ30AXKp_8^N_p$) ztyL7R*Mz5uRrz$O6#Q)yAWj4P`O07G@`ZqZ$<=F_e=OqaVVeMPDIjvxvqX$h00000NkvXXu0mjf Dy4nIL diff --git a/docs/public/web-app-manifest-512x512.png b/docs/public/web-app-manifest-512x512.png deleted file mode 100644 index 503da02909ccdd347693ba502cc370db5e7c7c46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23100 zcmYIv1yoeu*Y?a1(k&e$je;QEjMCi#(v5U?3?U(@NT(puAxPKIC@I}t(j^_=MgPC| zTh3at&b{}XeRe!M&OQ+;O48UEzrW zJ;Ymsj*73Kgo+;$CxOcF$whBZF3lx#Ps^~pU9PcemTUBL(Y0afh|*TsRm-B5{-5&g z%*@V^911%NP9uu{{)KB%$iO3zW#E5*Pzz)b27KzBuu<3^e8<#{9tHt^WoRm(y7ta! zPDUg1CMFMhFaZ=ya2Nq6k_SVHl4bwzQ)Z9}v15b$!zc839uWOIb&#vm(*3_l=<%LG zh(O;k_%ay&ejhFr=m)&8OV`%=-wSlW3p2=Ri%Fx5MBE_{1VQNVTo(fnFEHRptgrmL z5BlCwf?g{>Ebs&mt^6P#g!W{v=1mHSasSR!XAb^BOufp}>)i2oCsVLS*u4*0>a00wnJdtE;u z%Rq%7=~$LMu|7Mn?0jq@kVwj5Mjhc&{ZL&kocgXx_7v96M+<{PppcheFsTWbT!&1v zmq~i!LTQjP*uurHx1z;RU=A7=)WEb~&>T@|3LU-o74&8wp};p4BTzp6TM@2=>|Of~ zlI`)_H|c+}qg4bZ9a+wE`Nz#W!mWGySILuPUyidN(8pvgf4K%cD?>XKYdUAg*VA14 zEky*%Tro5LAOEun1IKDqKwm66l>bwQN@QjbEyWBo|JT(V9iqCCM+DHoI=rnuWej-B z)?rl~`e}dxn;DXh$O9ipU(b1v*ID;&kebCTP2ude9qf+&k`>Pl*$aA!0 zCXgO~m*Rh`>?2>DWI?jUUfrbsw;35=GeIx&bjd;PCcQ1teO++NqRX9W%tFs^oHWqv72l_uS z!SG2g@jP7OAlVdHqW^Rm3a&!0tIdQUM4s8p{%@Bbp1{C(DJmoQf0qrcBb4b0z<|42 zIq3oevFL|6T(NCO%73Cqii7^BfsjEdnh%pcu&xz(ggpZS^|P1@evrX; zIs|&T`;%V_Pz=zXxCGLJk!J@$gxBZAa+w`IL;&ljsH}=U@E3ufWQTABI3M~bZUYcQ zhy>hbf4@zgwcaw}S7OSZ1UQb2Z(kA+ge8P>cqCG^OU=6pGBaZeM�F*L@=gbczGr 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 new IllegalStateException("No playout device found")); - adm.dispose(); - - // Provide 10 ms frames of PCM 16‑bit audio. This example generates a sine tone. - final int sampleRate = 48000; - final int channels = 2; - final int bytesPerSample = channels * 2; // 16‑bit - final double frequency = 440.0; // A4 - final double twoPiFDivFs = 2 * Math.PI * frequency / sampleRate; - final int samplesPer10msPerChannel = sampleRate / 100; // 480 samples/channel - final int totalSamplesPer10ms = samplesPer10msPerChannel * channels; // e.g., 960 samples - final double[] phase = new double[] {0.0}; - - AudioSource source = (audioSamples, nSamples, nBytesPerSample, nChannels, samplesPerSec) -> { - // Ensure caller requested matches our configuration - if (nBytesPerSample != bytesPerSample || nChannels != channels || samplesPerSec != sampleRate) { - // Fill silence if formats mismatch - java.util.Arrays.fill(audioSamples, (byte) 0); - return totalSamplesPer10ms; - } - - // Generate interleaved stereo sine wave - int idx = 0; - for (int i = 0; i < samplesPer10msPerChannel; i++) { - short s = (short) (Math.sin(phase[0]) * 32767); - // left - audioSamples[idx++] = (byte) (s & 0xFF); - audioSamples[idx++] = (byte) ((s >> 8) & 0xFF); - // right - audioSamples[idx++] = (byte) (s & 0xFF); - audioSamples[idx++] = (byte) ((s >> 8) & 0xFF); - - phase[0] += twoPiFDivFs; - - if (phase[0] > Math.PI * 2) { - phase[0] -= Math.PI * 2; - } - } - return totalSamplesPer10ms; // number of samples written across all channels - }; - - AudioPlayer player = new AudioPlayer(); - player.setAudioDevice(speaker); - player.setAudioSource(source); - - player.start(); - // ... playout running ... - player.stop(); - } -} -``` - -## Data format -- The player requests 10 ms frames as 16‑bit little‑endian PCM via `AudioSource#onPlaybackData`. -- Return value must be the number of samples written across all channels for that 10 ms frame. - -## Tips -- If your synthesis/decoder operates at a different rate or channel layout, convert using the [Audio Converter](/tools/audio/audio-converter) before writing into the output buffer. - -## API reference -- `setAudioDevice(AudioDevice device)` – choose output device -- `setAudioSource(AudioSource source)` – provide playout frames -- `start()` / `stop()` – control the playout lifecycle diff --git a/docs/tools/audio/audio-recorder.md b/docs/tools/audio/audio-recorder.md deleted file mode 100644 index b0113b6..0000000 --- a/docs/tools/audio/audio-recorder.md +++ /dev/null @@ -1,65 +0,0 @@ -# Audio Recorder - -The AudioRecorder is a small helper that captures audio from a selected input device and forwards PCM frames to your implementation of `AudioSink`. It manages a native `AudioDeviceModule` internally and provides idempotent start/stop. - -API: `dev.onvoid.webrtc.media.audio.AudioRecorder` - -## When to use it -- You want a simple way to record microphone input without wiring a full PeerConnection. -- You need raw 16‑bit PCM frames (10 ms) delivered to your code for analysis, file writing, or custom processing. - -See also: [Audio Device Selection](/guide/audio/audio-devices), [Audio Processing](/guide/audio/audio-processing), [Custom Audio Source](/guide/audio/custom-audio-source). - -## Key concepts -- Device selection: Provide an `AudioDevice` representing the input device (microphone) before starting. -- Data delivery: Implement `AudioSink` to receive recorded frames. -- Lifecycle: `start()` initializes and starts capture once; `stop()` halts and releases native resources. - -## Basic usage - -```java -import dev.onvoid.webrtc.media.audio.AudioRecorder; -import dev.onvoid.webrtc.media.audio.AudioSink; -import dev.onvoid.webrtc.media.audio.AudioDevice; -import dev.onvoid.webrtc.media.audio.AudioDeviceModule; - -public class MicRecorderExample { - public static void main(String[] args) { - // Pick a recording device (microphone). You can enumerate via MediaDevices.getAudioCaptureDevices() - AudioDevice mic = ... - - // Implement a sink to receive 10 ms PCM frames - AudioSink sink = (audioSamples, nSamples, nBytesPerSample, nChannels, samplesPerSec, totalDelayMS, clockDrift) -> { - // audioSamples: little‑endian 16‑bit PCM - // nSamples: total samples across all channels for this 10 ms frame - // nBytesPerSample: typically 2 for 16‑bit - // nChannels: number of channels (1 = mono, 2 = stereo) - // samplesPerSec: sample rate (e.g., 48000) - // totalDelayMS, clockDrift: diagnostics - // TODO: write to file, analyzer, encoder, etc. - }; - - AudioRecorder recorder = new AudioRecorder(); - recorder.setAudioDevice(mic); - recorder.setAudioSink(sink); - - recorder.start(); - // ... capture running ... - recorder.stop(); - } -} -``` - -## Data format -- Frames are delivered every 10 ms as 16‑bit little‑endian PCM in a `byte[]`. -- `nSamples` refers to the number of samples across all channels within the 10 ms frame. Example: 48 kHz stereo → (48000/100)×2 = 960×2 = 1920 samples. - -## Tips -- Apply echo cancellation, AGC, and noise suppression via the [Audio Processing](/guide/audio/audio-processing) guide if needed. -- If you need to resample or remix, use the [Audio Converter](/tools/audio/audio-converter). -- Device selection details and best practices are covered in [Audio Device Selection](/guide/audio/audio-devices). - -## API reference -- `setAudioDevice(AudioDevice device)` – choose input device -- `setAudioSink(AudioSink sink)` – receive captured frames -- `start()` / `stop()` – control the capture lifecycle diff --git a/docs/tools/audio/voice-activity-detector.md b/docs/tools/audio/voice-activity-detector.md deleted file mode 100644 index ea7edf9..0000000 --- a/docs/tools/audio/voice-activity-detector.md +++ /dev/null @@ -1,104 +0,0 @@ -# Voice Activity Detector - -The Voice Activity Detector (VAD) helps you determine when speech is present in an audio stream. It analyzes short chunks of PCM audio and returns the probability that the chunk contains voice. - -This can be used to: -- Drive push-to-talk or auto-mute logic -- Skip encoding/sending silence to save bandwidth -- Trigger UI indicators when the user is speaking - -API: `dev.onvoid.webrtc.media.audio.VoiceActivityDetector` - -## Overview - -`VoiceActivityDetector` exposes a minimal API: -- `process(byte[] audio, int samplesPerChannel, int sampleRate)`: Analyze one audio frame. -- `getLastVoiceProbability()`: Retrieve the probability (0.0..1.0) that the last processed frame contained voice. -- `dispose()`: Release native resources. Always call this when done. - -Internally, VAD uses a native implementation optimized for real-time analysis. The class itself does not perform resampling or channel mixing, so provide audio matching the given `sampleRate` and expected format. - -## Audio format expectations - -- PCM signed 16-bit little-endian (typical Java byte[] from microphone capture via this library) -- Mono is recommended. If you have stereo, downmix to mono before calling `process` or pass samples-per-channel accordingly -- Frame size: commonly 10 ms per call (e.g., 160 samples at 16 kHz for 10 ms) -- Supported sample rates: 8 kHz, 16 kHz, 32 kHz, 48 kHz (use one of these for best results) - -## Basic usage - -```java -import dev.onvoid.webrtc.media.audio.VoiceActivityDetector; - -// Create the detector -VoiceActivityDetector vad = new VoiceActivityDetector(); - -try { - // Example parameters - int sampleRate = 16000; // 16 kHz - int frameMs = 10; // 10 ms frames - int samplesPerChannel = sampleRate * frameMs / 1000; // 160 samples - - // audioFrame must contain 16-bit PCM data for one frame (mono) - byte[] audioFrame = new byte[samplesPerChannel * 2]; // 2 bytes per sample - - // Fill audioFrame from your audio source here - // ... - - // Analyze frame - vad.process(audioFrame, samplesPerChannel, sampleRate); - - // Query probability of voice in the last frame - float prob = vad.getLastVoiceProbability(); // 0.0 .. 1.0 - - boolean isSpeaking = prob >= 0.5f; // choose a threshold that works for your app - -} -finally { - // Always release resources - vad.dispose(); -} -``` - -## Continuous processing loop - -```java -VoiceActivityDetector vad = new VoiceActivityDetector(); - -try { - int sampleRate = 16000; - int frameMs = 10; - int samplesPerChannel = sampleRate * frameMs / 1000; // 160 samples - byte[] audioFrame = new byte[samplesPerChannel * 2]; - - while (running) { - // Read PCM frame from your capture pipeline into audioFrame - // ... - - vad.process(audioFrame, samplesPerChannel, sampleRate); - float prob = vad.getLastVoiceProbability(); - - if (prob > 0.8f) { - // High confidence of speech - // e.g., enable VU meter, unmute, or mark active speaker - } - else { - // Likely silence or noise - } - } -} -finally { - vad.dispose(); -} -``` - -## Tips and best practices - -- Threshold selection: Start with 0.5–0.8 and tune for your environment. -- Frame size consistency: Use a consistent frame duration and sample rate. -- Resource management: VAD holds native resources; ensure `dispose()` is called. -- Preprocessing: Consider using `AudioProcessing` (noise suppression, gain control) before VAD for improved robustness in noisy environments. See the Audio Processing guide. - -## Related guides - -- [Audio Processing](/guide/audio/audio-processing) \ No newline at end of file diff --git a/docs/tools/desktop/power-management.md b/docs/tools/desktop/power-management.md deleted file mode 100644 index 241c382..0000000 --- a/docs/tools/desktop/power-management.md +++ /dev/null @@ -1,61 +0,0 @@ -# Power Management - -The `PowerManagement` utility allows your application to keep the display awake and prevent the operating system from idling to sleep while the user is considered "active" by your app. This is especially useful during screen sharing, presentations, or long-running desktop capture sessions where user input may be minimal. - -API: `dev.onvoid.webrtc.media.video.desktop.PowerManagement` - -## Overview - -- **Purpose**: Temporarily prevent the system from sleeping due to user idle. -- **Scope**: Affects display sleep/idle behavior while enabled. -- **Cross‑platform**: Implements native integrations for Windows, Linux, and macOS. -- **Responsibility**: You must explicitly disable the assertion when you are done. - -Key methods: -- `void enableUserActivity()` – Declare the user as active; prevents idle sleep. -- `void disableUserActivity()` – Revoke the assertion; system idle behavior resumes normally. - -## Typical usage - -Call `enableUserActivity()` when you start an operation that must keep the display awake (e.g., desktop capture or a presentation). Always pair it with `disableUserActivity()` (for example, in a `finally` block) to restore the normal power behavior. - -```java -import dev.onvoid.webrtc.media.video.desktop.PowerManagement; - -PowerManagement pm = new PowerManagement(); - -// Example: keep display awake during a screen sharing session -pm.enableUserActivity(); -try { - // Start and run your desktop capture / screen sharing pipeline - // ... -} -finally { - // Always restore normal behavior - pm.disableUserActivity(); -} -``` - -## Integration tips - -- Lifetime management: Keep the `PowerManagement` instance for as long as you need the assertion. It's safe to call `enableUserActivity()` once at the start and `disableUserActivity()` once at the end. -- Fail‑safe: If your workflow can terminate unexpectedly, ensure `disableUserActivity()` is called (e.g., in `finally` blocks, shutdown hooks, or close handlers). -- Minimal footprint: Only enable while strictly necessary. Do not keep the assertion enabled longer than needed. - -## Platform notes - -- **Windows**: Uses native Windows power APIs to request that the display remain on while enabled. -- **Linux** (Freedesktop environments): Uses DBus screensaver inhibition (e.g., org.freedesktop.ScreenSaver) where available. -- **macOS**: Uses macOS power management assertions to prevent display sleep while enabled. - -Exact mechanisms are handled by the native layer; your Java code remains the same across platforms. - -## When to use - -- While capturing or sharing the desktop to prevent the monitor from sleeping during inactivity. -- During long‑running, unattended demos, playback, or monitoring dashboards where user input is infrequent. - -## Related guides - -- [Desktop Capture](/guide/video/desktop-capture) -- [Logging](/guide/monitoring/logging) diff --git a/docs/tools/desktop/screen-capturer.md b/docs/tools/desktop/screen-capturer.md deleted file mode 100644 index 5775a47..0000000 --- a/docs/tools/desktop/screen-capturer.md +++ /dev/null @@ -1,112 +0,0 @@ -# Screen Capturer - -The `ScreenCapturer` enumerates and captures full desktop screens/monitors. Use it to list available screens and to drive screen-source selection for desktop capture workflows. - -API: `dev.onvoid.webrtc.media.video.desktop.ScreenCapturer` - -## Overview - -- Purpose: Discover and capture full screens (monitors). -- Pairs with: `VideoDesktopSource` to produce a capturable video track from a selected screen ID. -- Common ops: list screens, select one, configure capture parameters on `DesktopCapturer`, start capture via callback, or pass the ID to `VideoDesktopSource`. -- Resource management: Call `dispose()` when finished to free native resources. - -Key methods (inherited from `DesktopCapturer`): -- `List getDesktopSources()` – enumerate available screens -- `void selectSource(DesktopSource source)` – choose the screen to capture -- `void setFocusSelectedSource(boolean focus)` – try to focus the selected source during capture -- `void setMaxFrameRate(int maxFrameRate)` – cap the capture FPS -- `void start(DesktopCaptureCallback callback)` – begin capturing; frames are delivered via callback -- `void captureFrame()` – request a single frame (manual capture) -- `void dispose()` – release resources - -## Typical usage: enumerate screens - -```java -import dev.onvoid.webrtc.media.video.desktop.DesktopSource; -import dev.onvoid.webrtc.media.video.desktop.ScreenCapturer; -import java.util.List; - -ScreenCapturer screenCapturer = new ScreenCapturer(); -try { - List screens = screenCapturer.getDesktopSources(); - for (DesktopSource s : screens) { - System.out.printf("Screen: %s (ID: %d)%n", s.title, s.id); - } -} -finally { - screenCapturer.dispose(); -} -``` - -## Selecting a screen and starting capture with a callback - -```java -import dev.onvoid.webrtc.media.video.desktop.*; -import dev.onvoid.webrtc.media.video.VideoFrame; - -ScreenCapturer capturer = new ScreenCapturer(); -try { - // pick the first screen - DesktopSource screen = capturer.getDesktopSources().stream().findFirst() - .orElseThrow(() -> new IllegalStateException("No screens found")); - - capturer.selectSource(screen); - capturer.setMaxFrameRate(30); - capturer.setFocusSelectedSource(false); - - DesktopCaptureCallback callback = (result, frame) -> { - if (result == DesktopCapturer.Result.SUCCESS && frame != null) { - // process VideoFrame - } - }; - - capturer.start(callback); - - // Optionally trigger ad-hoc capture - capturer.captureFrame(); -} -finally { - capturer.dispose(); -} -``` - -## Using with VideoDesktopSource to create a VideoTrack - -For most WebRTC pipelines, you will create a `VideoDesktopSource` and set the selected screen ID: - -```java -import dev.onvoid.webrtc.media.video.VideoDesktopSource; -import dev.onvoid.webrtc.media.video.desktop.*; - -ScreenCapturer sc = new ScreenCapturer(); -DesktopSource screen = sc.getDesktopSources().get(0); - -VideoDesktopSource vds = new VideoDesktopSource(); -vds.setFrameRate(30); -vds.setMaxFrameSize(1920, 1080); - -// Select the screen (isWindow = false) -vds.setSourceId(screen.id, false); - -// Start the source and use it to create a VideoTrack in your PeerConnection -vds.start(); - -// ... - -// cleanup -vds.stop(); -vds.dispose(); -sc.dispose(); -``` - -## Integration tips - -- If screens can change (hot‑plug monitors), refresh `getDesktopSources()` as needed. -- Use `setMaxFrameRate` to limit capture load on the system. -- Prefer using `VideoDesktopSource` for WebRTC pipelines; keep `ScreenCapturer` for discovery and advanced control. - -## Related guides - -- [Desktop Capture](/guide/video/desktop-capture) -- [Power Management](/tools/desktop/power-management) diff --git a/docs/tools/desktop/window-capturer.md b/docs/tools/desktop/window-capturer.md deleted file mode 100644 index a92e4a3..0000000 --- a/docs/tools/desktop/window-capturer.md +++ /dev/null @@ -1,105 +0,0 @@ -# Window Capturer - -The `WindowCapturer` enumerates and captures individual application windows. Use it to list open windows and to drive window-source selection for desktop capture workflows. - -API: `dev.onvoid.webrtc.media.video.desktop.WindowCapturer` - -## Overview - -- Purpose: Discover and capture specific windows. -- Pairs with: `VideoDesktopSource` to create a video source capturing the chosen window ID. -- Common ops: list windows, select one, configure capture parameters, start capture via callback, or pass the window ID to `VideoDesktopSource`. -- Resource management: Call `dispose()` when finished to free native resources. - -Key methods (inherited from `DesktopCapturer`): -- `List getDesktopSources()` – enumerate available windows -- `void selectSource(DesktopSource source)` – choose which window to capture -- `void setFocusSelectedSource(boolean focus)` – attempt to focus/raise the selected window -- `void setMaxFrameRate(int maxFrameRate)` – limit the capture frame rate -- `void start(DesktopCaptureCallback callback)` – start capture, frames via callback -- `void captureFrame()` – request a single capture -- `void dispose()` – release resources - -## Typical usage: enumerate windows - -```java -import dev.onvoid.webrtc.media.video.desktop.DesktopSource; -import dev.onvoid.webrtc.media.video.desktop.WindowCapturer; -import java.util.List; - -WindowCapturer windowCapturer = new WindowCapturer(); -try { - List windows = windowCapturer.getDesktopSources(); - for (DesktopSource w : windows) { - System.out.printf("Window: %s (ID: %d)%n", w.title, w.id); - } -} -finally { - windowCapturer.dispose(); -} -``` - -## Selecting a window and starting capture with a callback - -```java -import dev.onvoid.webrtc.media.video.desktop.*; -import dev.onvoid.webrtc.media.video.VideoFrame; - -WindowCapturer capturer = new WindowCapturer(); -try { - DesktopSource window = capturer.getDesktopSources().stream().findFirst() - .orElseThrow(() -> new IllegalStateException("No windows found")); - - capturer.selectSource(window); - capturer.setMaxFrameRate(30); - capturer.setFocusSelectedSource(true); // optional - - DesktopCaptureCallback callback = (result, frame) -> { - if (result == DesktopCapturer.Result.SUCCESS && frame != null) { - // process VideoFrame for the selected window - } - }; - - capturer.start(callback); - capturer.captureFrame(); -} -finally { - capturer.dispose(); -} -``` - -## Using with VideoDesktopSource to create a VideoTrack - -```java -import dev.onvoid.webrtc.media.video.VideoDesktopSource; -import dev.onvoid.webrtc.media.video.desktop.*; - -WindowCapturer wc = new WindowCapturer(); -DesktopSource window = wc.getDesktopSources().get(0); - -VideoDesktopSource vds = new VideoDesktopSource(); -vds.setFrameRate(30); -vds.setMaxFrameSize(1280, 720); - -// Select the window (isWindow = true) -vds.setSourceId(window.id, true); - -vds.start(); - -// ... - -vds.stop(); -vds.dispose(); -wc.dispose(); -``` - -## Integration tips - -- Window availability is dynamic; refresh `getDesktopSources()` if the set of open windows changes. -- Not all OSes allow focusing/raising another app’s window; `setFocusSelectedSource` behavior may vary by platform. -- If the window is minimized or occluded, the captured content may be affected depending on platform. - -## Related guides - -- [Desktop Capture](/guide/video/desktop-capture) -- [Power Management](/tools/desktop/power-management) diff --git a/docs/tools/index.md b/docs/tools/index.md deleted file mode 100644 index 9e8a7f4..0000000 --- a/docs/tools/index.md +++ /dev/null @@ -1,41 +0,0 @@ -# Tools Overview - -This section collects small, focused helpers that make it easier to work with audio, video, and desktop capture features without wiring a full PeerConnection. Each utility provides a narrow, well‑defined API with simple start/stop lifecycles and is safe to integrate into custom pipelines. - -Use these pages to pick the right tool and jump straight to code examples. - -## Audio - -- [Audio Converter](/tools/audio/audio-converter) — Resample and remix 10 ms PCM frames between rates and channel layouts. -- [Audio Recorder](/tools/audio/audio-recorder) — Capture microphone input and receive 10 ms PCM frames via an `AudioSink`. -- [Audio Player](/tools/audio/audio-player) — Play PCM audio to an output device by supplying frames via an `AudioSource`. -- [Voice Activity Detector](/tools/audio/voice-activity-detector) — Estimate speech probability for short PCM frames. - -## Video - -- [Video Buffer Converter](/tools/video/video-buffer-converter) — Convert between I420 and common FourCC pixel formats (e.g., RGBA, NV12). -- [Video Capture](/tools/video/video-capturer) — Control a camera device, configure capabilities, and deliver frames to a sink. - -## Desktop capture - -- [Screen Capturer](/tools/desktop/screen-capturer) — Enumerate and capture full desktop screens/monitors. -- [Window Capturer](/tools/desktop/window-capturer) — Enumerate and capture individual application windows. -- [Power Management](/tools/desktop/power-management) — Keep the display awake during capture/presentations. - -## How these fit together - -- Capture: Use Video Capture for cameras, Screen/Window Capturer for desktop sources. -- Process/Analyze: Convert pixel formats with Video Buffer Converter; analyze audio with Voice Activity Detector. -- I/O: Use Audio Recorder to ingest microphone PCM; Audio Player to render PCM. -- System integration: Use Power Management to prevent the OS from sleeping during long running sessions. - -## Related guides - -- [Camera Capture](/guide/video/camera-capture) -- [Desktop Capture](/guide/video/desktop-capture) -- [Custom Video Source](/guide/video/custom-video-source) -- [Audio Device Selection](/guide/audio/audio-devices) -- [Audio Processing](/guide/audio/audio-processing) -- [RTC Stats](/guide/monitoring/rtc-stats) - -For API details, see the [JavaDoc](https://javadoc.io/doc/dev.onvoid.webrtc/webrtc-java/latest/index.html). diff --git a/docs/tools/video/video-buffer-converter.md b/docs/tools/video/video-buffer-converter.md deleted file mode 100644 index bda9068..0000000 --- a/docs/tools/video/video-buffer-converter.md +++ /dev/null @@ -1,145 +0,0 @@ -# Video Buffer Converter - -The VideoBufferConverter provides fast pixel format conversions between WebRTC's internal I420 video frame buffers and other formats identified by a FourCC. Conversions are delegated to optimized native routines. - -API: `dev.onvoid.webrtc.media.video.VideoBufferConverter` - -## When to use it -- Rendering frames in UI toolkits that expect interleaved RGB(A) byte layouts. -- Preparing frames for encoders/decoders that require specific pixel formats. -- Importing external pixel data (e.g., RGBA, NV12) into the WebRTC pipeline as I420. - -See also: [Video Capture](/tools/video/video-capturer), [Custom Video Source](/guide/video/custom-video-source). - -## Supported operations - -1) From I420 to other pixel formats -- `convertFromI420(VideoFrameBuffer src, byte[] dst, FourCC fourCC)` -- `convertFromI420(VideoFrameBuffer src, ByteBuffer dst, FourCC fourCC)` - -2) From other pixel formats to I420 -- `convertToI420(byte[] src, I420Buffer dst, FourCC fourCC)` -- `convertToI420(ByteBuffer src, I420Buffer dst, FourCC fourCC)` - -Notes: -- The VideoFrameBuffer is internally converted to I420 if necessary using `VideoFrameBuffer#toI420()` before transformation. -- When using ByteBuffer destinations/sources, direct buffers use a zero-copy native path for best performance; otherwise, the method will use the backing array or a temporary array. - -## FourCC formats - -The target/source pixel layout is selected with `dev.onvoid.webrtc.media.FourCC`. Common values include: -- `FourCC.RGBA` – 4 bytes per pixel, RGBA order (commonly used with BufferedImage TYPE_4BYTE_ABGR interop, see example below) -- `FourCC.ARGB`, `FourCC.ABGR`, `FourCC.BGRA` – other 32-bit packed variants -- `FourCC.NV12`, `FourCC.NV21` – 4:2:0 semi-planar YUV formats - -Consult the FourCC enum in your version for the complete list. - -## Buffer sizing - -You must allocate destination buffers large enough for the chosen format: -- For 32-bit RGBA-like formats: `width * height * 4` bytes -- For NV12/NV21: `width * height * 3 / 2` bytes -- For other layouts, compute according to their specification - -Attempting to convert into undersized buffers will result in an error. - -## Example: Convert VideoFrame to BufferedImage - -This example demonstrates converting a WebRTC `VideoFrame` to a Java `BufferedImage` using RGBA output. - -```java -import dev.onvoid.webrtc.media.FourCC; -import dev.onvoid.webrtc.media.video.VideoBufferConverter; -import dev.onvoid.webrtc.media.video.VideoFrame; -import dev.onvoid.webrtc.media.video.VideoFrameBuffer; - -import java.awt.image.BufferedImage; -import java.awt.image.DataBufferByte; - -public void onVideoFrame(VideoFrame frame) { - try { - // Get frame dimensions - VideoFrameBuffer frameBuffer = frame.buffer; - int frameWidth = frameBuffer.getWidth(); - int frameHeight = frameBuffer.getHeight(); - - // Create a BufferedImage with ABGR format (compatible with RGBA conversion) - BufferedImage image = new BufferedImage(frameWidth, frameHeight, BufferedImage.TYPE_4BYTE_ABGR); - - // Get the underlying byte array from the BufferedImage - byte[] imageBuffer = ((DataBufferByte) image.getRaster().getDataBuffer()).getData(); - - // Convert the frame buffer from I420 format to RGBA format - VideoBufferConverter.convertFromI420(frameBuffer, imageBuffer, FourCC.RGBA); - - // Now you can use the BufferedImage for display or further processing - // e.g., display in Swing/JavaFX - } - catch (Exception e) { - // Handle conversion errors - e.printStackTrace(); - } - finally { - // Always release the frame when done - frame.release(); - } -} -``` - -How it works: -1. Create a `BufferedImage` sized to the frame. -2. Access its backing `byte[]` via `DataBufferByte`. -3. Convert the VideoFrameBuffer from I420 to RGBA into the image buffer. - -Tip: If you have a direct NIO ByteBuffer (e.g., for native interop), use the ByteBuffer overload to keep a direct native path. - -## Example: Import RGBA data into I420 - -```java -import dev.onvoid.webrtc.media.FourCC; -import dev.onvoid.webrtc.media.video.VideoBufferConverter; -import dev.onvoid.webrtc.media.video.VideoFrame; -import dev.onvoid.webrtc.media.video.VideoFrameBuffer; - -import java.awt.image.BufferedImage; -import java.awt.image.DataBufferByte; - -public void onImage(BufferedImage image) { - // Get image dimensions - int imageWidth = image.getWidth(); - int imageHeight = image.getHeight(); - - // Create a I420Buffer - NativeI420Buffer i420 = NativeI420Buffer.allocate(imageWidth, imageHeight); - - // Get the underlying byte array from the BufferedImage - byte[] imageBuffer = ((DataBufferByte) image.getRaster().getDataBuffer()).getData(); - - try { - // In this example, we assume the BufferedImage is in 4 byte ABGR format - VideoBufferConverter.convertToI420(imageBuffer, i420, FourCC.RGBA); - - // Now you can use the I420Buffer, e.g., wrap in a VideoFrame - } - catch (Exception e) { - // Handle conversion errors - e.printStackTrace(); - } - finally { - // Always release the buffer when done - i420.release(); - } -} -``` - -## Error handling and edge cases -- All methods throw `NullPointerException` if src/dst is null; ensure proper checks. -- `ByteBuffer` destinations must be writable (not read-only) for `convertFromI420`. -- Ensure the correct FourCC is used for the actual memory layout you pass/expect. -- Beware of frame rotation metadata; conversions do not rotate pixels. Handle `VideoFrame.rotation` separately if your renderer requires upright images. - -## Related -- [Video Capture](/tools/video/video-capturer) -- [Custom Video Source](/guide/video/custom-video-source) -- [Screen Capturer](/tools/desktop/screen-capturer) -- [Window Capturer](/tools/desktop/window-capturer) diff --git a/docs/tools/video/video-capturer.md b/docs/tools/video/video-capturer.md deleted file mode 100644 index 77f8d8d..0000000 --- a/docs/tools/video/video-capturer.md +++ /dev/null @@ -1,110 +0,0 @@ -# Video Capture - -The `VideoCapture` class represents a controllable video capture device and coordinates device selection, capability negotiation, frame delivery to a sink, and lifecycle/resource management. - -API: `dev.onvoid.webrtc.media.video.VideoCapture` - -## Overview - -- Purpose: Control a physical or virtual video input device and deliver frames to a sink. -- Typical workflow: set device âžœ set capability âžœ set sink âžœ start âžœ stop âžœ dispose. -- Resource management: Always call `dispose()` to release native resources. -- Threading: Methods are not guaranteed to be thread‑safe; synchronize externally if accessed from multiple threads. - -Key methods: -- `void setVideoCaptureDevice(VideoDevice device)` – select the camera/device to bind. -- `void setVideoCaptureCapability(VideoCaptureCapability capability)` – configure desired resolution, frame rate, pixel format, etc. -- `void setVideoSink(VideoTrackSink sink)` – register/replace the sink that will receive frames. -- `void start()` – begin asynchronous capture and frame delivery. -- `void stop()` – stop capture (idempotent). -- `void dispose()` – release native resources; implicitly stops if running. - -Related types: -- `VideoDevice` – describes a capturable device (enumerate via your platform/device utilities). -- `VideoCaptureCapability` – resolution, FPS, and pixel format preferences. -- `VideoTrackSink` – consumer that receives `VideoFrame` callbacks. - -## Typical usage - -```java -import dev.onvoid.webrtc.media.video.*; - -// 1) Create capture -VideoCapture capture = new VideoCapture(); - -try { - // 2) Select a device (obtained from your device enumeration logic) - VideoDevice device = /* obtain a VideoDevice */; - capture.setVideoCaptureDevice(device); - - // 3) Configure capability - VideoCaptureCapability cap = new VideoCaptureCapability(); - cap.width = 1280; - cap.height = 720; - cap.maxFPS = 30; - // cap.pixelFormat = ... // if applicable in your build - capture.setVideoCaptureCapability(cap); - - // 4) Provide a sink to receive frames - VideoTrackSink sink = frame -> { - // Consume VideoFrame - // e.g., render, encode, or forward to a WebRTC VideoSource/Track - }; - capture.setVideoSink(sink); - - // 5) Start capture - capture.start(); - - // ... capture is running, frames delivered to sink ... - - // 6) Stop capture - capture.stop(); -} -finally { - // 7) Cleanup - capture.dispose(); -} -``` - -Notes: -- Call `setVideoCaptureDevice` and `setVideoCaptureCapability` before `start()`. -- You may call `setVideoSink` before or after `start()`; passing `null` detaches the sink (if supported), dropping frames until a new sink is set. -- Some capability values may be negotiated to the nearest supported values by the underlying platform. - -## Integration with WebRTC tracks - -While `VideoCapture` handles raw capture, most WebRTC pipelines use a `VideoSource`/`VideoTrack` abstraction. If you need to feed frames into a `VideoTrack`, use or implement a sink that forwards frames to your `VideoSource` (or use a higher‑level helper provided by this project/examples). - -Example sketch: - -```java -VideoTrackSink sink = frame -> { - // Convert/forward frame into your WebRTC VideoSource or renderer -}; - -capture.setVideoSink(sink); -capture.start(); -``` - -If you need pixel format conversion, see `VideoBufferConverter`. - -## Error handling and lifecycle - -- Constructor: Initializes native resources; failures may surface as runtime exceptions from native code. -- `IllegalStateException`: Thrown if methods are invoked after disposal or when prerequisites are missing. -- Idempotency: `start()` and `stop()` are intended to be safe to call multiple times (implementation‑dependent no‑op if already in that state). -- Always call `dispose()` in a `finally` block to avoid leaking native resources. - -## Tips - -- Device changes (plug/unplug cameras) may require re‑enumeration and re‑selection via `setVideoCaptureDevice`. -- If frames need scaling or color conversion, use `VideoBufferConverter` before feeding frames to encoders or renderers. -- Synchronize access if multiple threads change device, capability, or sink while capturing. - -## Related guides - -- [Camera Capture](/guide/video/camera-capture) -- [Custom Video Source](/guide/video/custom-video-source) -- [Screen Capturer](/tools/desktop/screen-capturer) -- [Window Capturer](/tools/desktop/window-capturer) -- [Power Management](/tools/desktop/power-management) diff --git a/docs/tsconfig.json b/docs/tsconfig.json deleted file mode 100644 index fb71cb5..0000000 --- a/docs/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "compilerOptions": { - "target": "esnext", - "module": "esnext", - "moduleResolution": "node", - "strict": true, - "jsx": "preserve" - }, - "include": [ - "**/.vitepress/**/*" - ] -} \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..6ad9d08 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,15 @@ +[versions] +nmcp = "1.3.0" +cmakePlugin = "0.9.6" +junit = "5.14.1" + +[libraries] +# Test dependencies +junit-jupiter-engine = { group = "org.junit.jupiter", name = "junit-jupiter-engine", version.ref = "junit" } +junit-jupiter-api = { group = "org.junit.jupiter", name = "junit-jupiter-api", version.ref = "junit" } +junit-jupiter-params = { group = "org.junit.jupiter", name = "junit-jupiter-params", version.ref = "junit" } +junit-platform-launcher = { group = "org.junit.platform", name = "junit-platform-launcher" } + +[plugins] +nmcp = { id = "com.gradleup.nmcp", version.ref = "nmcp" } +cmake = { id = "io.github.tomaki19.gradle-cmake-plugin", version.ref = "cmakePlugin" } \ No newline at end of file diff --git a/pom.xml b/pom.xml deleted file mode 100644 index e33dace..0000000 --- a/pom.xml +++ /dev/null @@ -1,377 +0,0 @@ - - - 4.0.0 - - dev.onvoid.webrtc - webrtc-java-parent - 0.15.0-SNAPSHOT - pom - - webrtc-java-parent - - Java native interface implementation based on the free, open WebRTC - project. The goal of this project is to enable development of RTC - applications for desktop platforms running Java. - - https://github.com/devopvoid/webrtc-java - - - - a.andres - Alex Andres - andres.alex@pm.me - - - - - - The Apache Software License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - repo - - - - - GitHub - https://github.com/devopvoid/webrtc-java/issues - - - - scm:git:git://github.com/devopvoid/webrtc-java.git - scm:git:ssh://git@github.com/devopvoid/webrtc-java.git - https://github.com/devopvoid/webrtc-java/tree/main - HEAD - - - - ${maven.build.timestamp} - UTF-8 - yyyy-MM-dd HH:mm - - - - webrtc-jni - webrtc - webrtc-examples - - - - - - - - org.apache.maven.plugins - maven-antrun-plugin - 3.1.0 - - - org.apache.maven.plugins - maven-compiler-plugin - 3.11.0 - - - default-compile - - 9 - - - - - base-compile - - compile - - - - - module-info.java - - - - - - - 8 - - - 9 - - true - true - true - - - - org.sonatype.central - central-publishing-maven-plugin - 0.7.0 - true - - central - - webrtc-java-jni - - - - - org.apache.maven.plugins - maven-deploy-plugin - 3.1.4 - - - org.apache.maven.plugins - maven-gpg-plugin - 1.6 - - - sign-artifacts - verify - - sign - - - - --pinentry-mode - loopback - - - - - - - org.apache.maven.plugins - maven-install-plugin - 3.1.1 - - - org.apache.maven.plugins - maven-jar-plugin - 3.3.0 - - - true - - ${project.version} - ${maven.build.timestamp} - - - true - - - - org.apache.maven.plugins - maven-javadoc-plugin - 3.1.1 - - none - - - - attach-javadocs - - jar - - - false - - - - - - org.apache.maven.plugins - maven-project-info-reports-plugin - 3.0.0 - - - org.apache.maven.plugins - maven-release-plugin - 3.0.1 - - true - release - v@{project.version} - Prepare for next development iteration - Prepare release @{releaseLabel} - - - - org.apache.maven.plugins - maven-resources-plugin - 3.3.1 - - - org.apache.maven.plugins - maven-site-plugin - 3.8.2 - - - org.apache.maven.plugins - maven-source-plugin - 3.1.0 - - - attach-sources - - jar-no-fork - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 3.2.2 - - - org.apache.maven.plugins - maven-surefire-report-plugin - 3.2.2 - - - org.apache.maven.plugins - maven-failsafe-plugin - 3.2.2 - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.sonatype.central - central-publishing-maven-plugin - - - - - - - release - - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-javadoc-plugin - - - org.apache.maven.plugins - maven-gpg-plugin - - - - - - windows-x86_64 - - - windows - amd64 - - - - windows-x86_64 - webrtc.windows.x86_64 - - - - linux-x86_64 - - - linux - amd64 - - - - linux-x86_64 - webrtc.linux.x86_64 - - - - linux-aarch32 - - - linux - aarch32 - - - - linux-aarch32 - webrtc.linux.aarch32 - - - - linux-aarch64 - - - linux - aarch64 - - - - linux-aarch64 - webrtc.linux.aarch64 - - - - macos-x86_64 - - - mac - x86_64 - - - - macos-x86_64 - webrtc.macos.x86_64 - - - - macos-aarch64 - - - mac - aarch64 - - - - macos-aarch64 - webrtc.macos.aarch64 - - - - - - - - org.apache.maven.plugins - maven-project-info-reports-plugin - - - org.apache.maven.plugins - maven-surefire-report-plugin - - - - - - - org.junit.jupiter - junit-jupiter-api - 5.9.0 - test - - - org.junit.jupiter - junit-jupiter-engine - 5.9.0 - test - - - \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..c153b45 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,11 @@ +pluginManagement { + repositories { + gradlePluginPortal() + mavenCentral() + } +} + +rootProject.name = "webrtc-java-parent" + +include("webrtc-jni") +include("webrtc") diff --git a/webrtc-examples/pom.xml b/webrtc-examples/pom.xml deleted file mode 100644 index 6664b76..0000000 --- a/webrtc-examples/pom.xml +++ /dev/null @@ -1,97 +0,0 @@ - - - 4.0.0 - - - dev.onvoid.webrtc - webrtc-java-parent - 0.15.0-SNAPSHOT - - - webrtc-java-examples - - webrtc-java-examples - - - true - true - UTF-8 - 12.0.23 - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - - default-compile - compile - - compile - - - 17 - - - - base-compile - none - - - - 17 - - 17 - - - - - - - - src/main/resources - resources - - - - - - - ${project.groupId} - webrtc-java - ${project.version} - - - - org.eclipse.jetty - jetty-server - ${jetty.version} - - - org.eclipse.jetty.websocket - jetty-websocket-jetty-server - ${jetty.version} - - - org.eclipse.jetty - jetty-util - ${jetty.version} - - - - - com.fasterxml.jackson.core - jackson-databind - 2.16.1 - - - - org.slf4j - slf4j-jdk14 - 2.0.17 - - - \ No newline at end of file diff --git a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/client/SignalingManager.java b/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/client/SignalingManager.java deleted file mode 100644 index 2d6fd4e..0000000 --- a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/client/SignalingManager.java +++ /dev/null @@ -1,415 +0,0 @@ -/* - * Copyright 2025 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.examples.web.client; - -import java.net.URI; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; - -import com.fasterxml.jackson.databind.ObjectMapper; - -import dev.onvoid.webrtc.RTCIceCandidate; -import dev.onvoid.webrtc.RTCSessionDescription; - -import dev.onvoid.webrtc.examples.web.model.*; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Manages WebSocket signaling for WebRTC connections. - *

    - * This class handles the communication between peers during WebRTC connection establishment. - * It manages sending and receiving: - *

    - *

    - * The manager connects to a signaling server via WebSocket and translates WebRTC-related - * objects to JSON messages that can be transmitted over the signaling channel. - * - * @author Alex Andres - */ -public class SignalingManager { - - private static final Logger LOG = LoggerFactory.getLogger(SignalingManager.class); - - /** The WebSocket client used to communicate with the signaling server. */ - private final WebSocketClient signaling; - - /** JSON mapper for serializing and deserializing signaling messages. */ - private final ObjectMapper jsonMapper; - - /** Callback that is triggered when an offer message is received from a remote peer. */ - private Consumer onOfferReceived; - - /** Callback that is triggered when an answer message is received from a remote peer. */ - private Consumer onAnswerReceived; - - /** Callback that is triggered when an ICE candidate is received from a remote peer. */ - private Consumer onCandidateReceived; - - /** Callback that is triggered when a join message is received. */ - private Consumer onJoinReceived; - - /** Callback that is triggered when a leave message is received. */ - private Consumer onLeaveReceived; - - private String userId = "java-client"; - private String remotePeerId = "web-client"; - - - /** - * Creates a new SignalingManager with the specified URI and subprotocol. - * - * @param signalingUri The URI of the signaling server. - * @param subprotocol The WebSocket subprotocol to use. - */ - public SignalingManager(URI signalingUri, String subprotocol) { - this.signaling = new WebSocketClient(signalingUri, subprotocol); - this.jsonMapper = new ObjectMapper(); - - setupSignaling(); - - LOG.info("SignalingManager created"); - } - - /** - * Connects to the signaling server. - * - * @return true if the connection was successful, false otherwise. - */ - public boolean connect() { - try { - CountDownLatch connectLatch = new CountDownLatch(1); - - signaling.connect() - .thenAccept(ws -> { - LOG.info("Connected to signaling server"); - connectLatch.countDown(); - }) - .exceptionally(e -> { - LOG.error("Failed to connect to signaling server", e); - connectLatch.countDown(); - return null; - }); - - // Wait for connection. - connectLatch.await(5, TimeUnit.SECONDS); - - return signaling.isConnected(); - } - catch (Exception e) { - LOG.error("Error connecting to signaling server", e); - return false; - } - } - - /** - * Disconnects from the signaling server. - */ - public void disconnect() { - if (isConnected()) { - signaling.disconnect(1000, "Client disconnecting"); - - LOG.info("Disconnected from signaling server"); - } - } - - /** - * Sends a join message to the signaling server. - * - * @param roomId The ID of the room to join. - */ - public void sendJoin(String roomId) { - try { - JoinMessage joinMessage = new JoinMessage(userId, roomId, "Java Client"); - - // Convert to JSON and send. - String joinMessageJson = jsonMapper.writeValueAsString(joinMessage); - signaling.sendMessage(joinMessageJson); - - LOG.info("Sent join message for room: {}", roomId); - } - catch (Exception e) { - LOG.error("Error creating JSON join message", e); - } - } - - /** - * Sends a session description (offer or answer) to the remote peer. - * - * @param sdp The session description to send. - */ - public void sendSessionDescription(RTCSessionDescription sdp) { - String type = sdp.sdpType.toString().toLowerCase(); - - try { - SessionDescriptionMessage message = new SessionDescriptionMessage( - type, - userId, - remotePeerId, - sdp.sdp - ); - - String messageJson = jsonMapper.writeValueAsString(message); - signaling.sendMessage(messageJson); - - LOG.info("Sent {} to remote peer", type); - } - catch (Exception e) { - LOG.error("Error creating JSON message", e); - } - } - - /** - * Sends an ICE candidate to the remote peer. - * - * @param candidate The ICE candidate to send. - */ - public void sendIceCandidate(RTCIceCandidate candidate) { - try { - IceCandidateMessage message = new IceCandidateMessage( - userId, - remotePeerId, - candidate.sdp, - candidate.sdpMid, - candidate.sdpMLineIndex - ); - - String candidateJson = jsonMapper.writeValueAsString(message); - signaling.sendMessage(candidateJson); - - LOG.info("Sent ICE candidate to remote peer"); - } - catch (Exception e) { - LOG.error("Error creating JSON message", e); - } - } - - /** - * Sets up the WebSocket signaling to handle incoming messages. - */ - private void setupSignaling() { - signaling.addMessageListener(message -> { - try { - // Parse the message to extract the type. - String type = jsonMapper.readTree(message).path("type").asText(); - MessageType messageType = MessageType.fromString(type); - - switch (messageType) { - case OFFER -> handleOfferMessage(message); - case ANSWER -> handleAnswerMessage(message); - case ICE_CANDIDATE -> handleIceCandidateMessage(message); - case JOIN -> handleJoinMessage(message); - case LEAVE -> handleLeaveMessage(message); - case HEARTBEAT_ACK -> LOG.info("Received: {}", type); - default -> LOG.info("Received message with unknown type: {}", type); - } - } - catch (Exception e) { - LOG.error("Error parsing message type", e); - } - }); - - signaling.addCloseListener(() -> { - LOG.info("Signaling connection closed"); - }); - - signaling.addErrorListener(error -> { - LOG.error("Signaling error", error); - }); - } - - /** - * Sets a callback to be invoked when an offer is received. - * - * @param callback The callback to invoke. - */ - public void setOnOfferReceived(Consumer callback) { - this.onOfferReceived = callback; - } - - /** - * Sets a callback to be invoked when an answer is received. - * - * @param callback The callback to invoke. - */ - public void setOnAnswerReceived(Consumer callback) { - this.onAnswerReceived = callback; - } - - /** - * Sets a callback to be invoked when an ICE candidate is received. - * - * @param callback The callback to invoke. - */ - public void setOnCandidateReceived(Consumer callback) { - this.onCandidateReceived = callback; - } - - /** - * Sets a callback to be invoked when a join message is received. - * - * @param callback The callback to invoke. - */ - public void setOnJoinReceived(Consumer callback) { - this.onJoinReceived = callback; - } - - /** - * Sets a callback to be invoked when a leave message is received. - * - * @param callback The callback to invoke. - */ - public void setOnLeaveReceived(Consumer callback) { - this.onLeaveReceived = callback; - } - - /** - * Sets the user ID for this client. - * - * @param userId The user ID to set. - */ - public void setUserId(String userId) { - this.userId = userId; - } - - /** - * Sets the remote peer ID. - * - * @param remotePeerId The remote peer ID to set. - */ - public void setRemotePeerId(String remotePeerId) { - this.remotePeerId = remotePeerId; - } - - /** - * Gets the user ID for this client. - * - * @return The user ID. - */ - public String getUserId() { - return userId; - } - - /** - * Gets the remote peer ID. - * - * @return The remote peer ID. - */ - public String getRemotePeerId() { - return remotePeerId; - } - - /** - * Checks if the signaling connection is established. - * - * @return true if connected, false otherwise. - */ - public boolean isConnected() { - return signaling != null && signaling.isConnected(); - } - - /** - * Handles an incoming offer message. - * - * @param message The JSON message containing an offer. - */ - private void handleOfferMessage(String message) { - if (onOfferReceived != null) { - try { - SessionDescriptionMessage sdpMessage = jsonMapper.readValue(message, SessionDescriptionMessage.class); - onOfferReceived.accept(sdpMessage); - } - catch (Exception e) { - LOG.error("Error parsing offer message", e); - } - } - } - - /** - * Handles an incoming answer message. - * - * @param message The JSON message containing an answer. - */ - private void handleAnswerMessage(String message) { - if (onAnswerReceived != null) { - try { - SessionDescriptionMessage sdpMessage = jsonMapper.readValue(message, SessionDescriptionMessage.class); - onAnswerReceived.accept(sdpMessage); - } - catch (Exception e) { - LOG.error("Error parsing answer message", e); - } - } - } - - /** - * Handles an incoming ICE candidate message. - * - * @param message The JSON message containing an ICE candidate. - */ - private void handleIceCandidateMessage(String message) { - if (onCandidateReceived != null) { - try { - IceCandidateMessage iceMessage = jsonMapper.readValue(message, IceCandidateMessage.class); - onCandidateReceived.accept(iceMessage); - } - catch (Exception e) { - LOG.error("Error parsing ICE candidate message", e); - } - } - } - - /** - * Handles an incoming join message. - * - * @param message The JSON message containing join information. - */ - private void handleJoinMessage(String message) { - if (onJoinReceived != null) { - try { - JoinMessage joinMessage = jsonMapper.readValue(message, JoinMessage.class); - onJoinReceived.accept(joinMessage); - } - catch (Exception e) { - LOG.error("Error parsing join message", e); - } - } - } - - /** - * Handles an incoming leave message. - * - * @param message The JSON message indicating a peer has left. - */ - private void handleLeaveMessage(String message) { - if (onLeaveReceived != null) { - try { - LeaveMessage leaveMessage = jsonMapper.readValue(message, LeaveMessage.class); - onLeaveReceived.accept(leaveMessage); - } - catch (Exception e) { - LOG.error("Error parsing join message", e); - } - } - } -} \ No newline at end of file diff --git a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/client/WebSocketClient.java b/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/client/WebSocketClient.java deleted file mode 100644 index e2a8762..0000000 --- a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/client/WebSocketClient.java +++ /dev/null @@ -1,453 +0,0 @@ -/* - * Copyright 2025 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.examples.web.client; - -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.WebSocket; -import java.nio.ByteBuffer; -import java.time.Duration; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; - -import dev.onvoid.webrtc.examples.web.model.SignalingMessage; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * A WebSocket client implementation using JDK internal WebSockets (java.net.http.WebSocket). - * This client supports secure WebSocket connections (WSS), message sending/receiving, - * and automatic heartbeat to keep the connection alive. - * - * @author Alex Andres - */ -public class WebSocketClient { - - private static final Logger LOG = LoggerFactory.getLogger(WebSocketClient.class); - - /** The interval between heartbeat messages in seconds to keep the WebSocket connection alive. */ - private static final long HEARTBEAT_INTERVAL_SECONDS = 15; - - /** JSON serializer/deserializer for processing WebSocket messages. */ - private final ObjectMapper jsonMapper = new ObjectMapper(); - - private final URI serverUri; - private final List subprotocols; - private final List> messageListeners; - private final List closeListeners; - private final List> errorListeners; - - private WebSocket webSocket; - private ScheduledExecutorService heartbeatExecutor; - private boolean connected = false; - - - /** - * Creates a new WebSocket client. - * - * @param serverUri The URI of the WebSocket server (e.g., "wss://localhost:8443/ws"). - * @param subprotocols The WebSocket subprotocols to use (e.g., "ws-signaling"). - */ - public WebSocketClient(URI serverUri, List subprotocols) { - this.serverUri = serverUri; - this.subprotocols = subprotocols; - this.messageListeners = new CopyOnWriteArrayList<>(); - this.closeListeners = new CopyOnWriteArrayList<>(); - this.errorListeners = new CopyOnWriteArrayList<>(); - } - - /** - * Creates a new WebSocket client with a single subprotocol. - * - * @param serverUri The URI of the WebSocket server. - * @param subprotocol The WebSocket subprotocol to use. - */ - public WebSocketClient(URI serverUri, String subprotocol) { - this(serverUri, List.of(subprotocol)); - } - - /** - * Connects to the WebSocket server. - * - * @return A CompletableFuture that completes when the connection is established. - */ - public CompletableFuture connect() { - if (connected) { - return CompletableFuture.completedFuture(webSocket); - } - - WebSocket.Listener listener = new WebSocketListener(); - - // Create an HTTP client that accepts all SSL certificates (useful for self-signed certs in development). - HttpClient client = HttpClient.newBuilder() - .sslContext(TrustAllCertificates.createSslContext()) - .connectTimeout(Duration.ofSeconds(10)) - .build(); - - // Build the WebSocket with our listener and subprotocols. - WebSocket.Builder wsBuilder = client.newWebSocketBuilder() - .connectTimeout(Duration.ofSeconds(10)); - - // Add subprotocols if provided. - if (subprotocols != null && !subprotocols.isEmpty()) { - for (String protocol : subprotocols) { - wsBuilder.subprotocols(protocol); - } - } - - LOG.info("Connecting to WebSocket server: {}", serverUri); - - return wsBuilder.buildAsync(serverUri, listener) - .thenApply(ws -> { - this.webSocket = ws; - this.connected = true; - - // Start heartbeat to keep connection alive. - startHeartbeat(); - - LOG.info("Connected to WebSocket server: {}", serverUri); - return ws; - }) - .exceptionally(ex -> { - LOG.error("Failed to connect to WebSocket server: {}", ex.getMessage()); - notifyErrorListeners(ex); - return null; - }); - } - - /** - * Sends a text message to the WebSocket server. - * - * @param message The message to send. - * - * @return A CompletableFuture that completes when the message is sent. - */ - public CompletableFuture sendMessage(String message) { - if (!connected || webSocket == null) { - return CompletableFuture.failedFuture( - new IllegalStateException("Not connected to WebSocket server")); - } - - LOG.debug("Sending message: {}", message); - - return webSocket.sendText(message, true); - } - - /** - * Closes the WebSocket connection. - * - * @param statusCode The WebSocket close status code. - * @param reason The reason for closing. - * - * @return A CompletableFuture that completes when the connection is closed. - */ - public CompletableFuture disconnect(int statusCode, String reason) { - if (!connected || webSocket == null) { - return CompletableFuture.completedFuture(null); - } - - stopHeartbeat(); - - LOG.info("Disconnecting from WebSocket server: {}", serverUri); - - return webSocket.sendClose(statusCode, reason) - .thenApply(ws -> { - this.connected = false; - this.webSocket = null; - return ws; - }); - } - - /** - * Adds a listener for incoming text messages. - * - * @param listener The message listener. - */ - public void addMessageListener(Consumer listener) { - messageListeners.add(listener); - } - - /** - * Removes a message listener. - * - * @param listener The message listener to remove. - */ - public void removeMessageListener(Consumer listener) { - messageListeners.remove(listener); - } - - /** - * Adds a listener for connection close events. - * - * @param listener The close listener. - */ - public void addCloseListener(Runnable listener) { - closeListeners.add(listener); - } - - /** - * Removes a close listener. - * - * @param listener The close listener to remove. - */ - public void removeCloseListener(Runnable listener) { - closeListeners.remove(listener); - } - - /** - * Adds a listener for connection errors. - * - * @param listener The error listener. - */ - public void addErrorListener(Consumer listener) { - errorListeners.add(listener); - } - - /** - * Removes an error listener. - * - * @param listener The error listener to remove. - */ - public void removeErrorListener(Consumer listener) { - errorListeners.remove(listener); - } - - /** - * Checks if the client is connected to the WebSocket server. - * - * @return true if connected, false otherwise. - */ - public boolean isConnected() { - return connected; - } - - /** - * Starts the heartbeat to keep the WebSocket connection alive. - */ - private void startHeartbeat() { - // Ensure any existing heartbeat is stopped. - stopHeartbeat(); - - heartbeatExecutor = Executors.newSingleThreadScheduledExecutor(r -> { - Thread t = new Thread(r, "websocket-heartbeat"); - t.setDaemon(true); - return t; - }); - - heartbeatExecutor.scheduleAtFixedRate(() -> { - if (connected && webSocket != null) { - LOG.debug("Sending heartbeat"); - - sendHeartbeat(); - } - }, HEARTBEAT_INTERVAL_SECONDS, HEARTBEAT_INTERVAL_SECONDS, TimeUnit.SECONDS); - } - - /** - * Sends a heartbeat message to the WebSocket server to keep the connection alive. - */ - private void sendHeartbeat() { - SignalingMessage heartbeat = new SignalingMessage("heartbeat"); - String heartbeatJson; - - try { - heartbeatJson = jsonMapper.writeValueAsString(heartbeat); - } - catch (JsonProcessingException e) { - LOG.error("Failed to send heartbeat", e); - return; - } - - sendMessage(heartbeatJson) - .exceptionally(ex -> { - LOG.error("Failed to send heartbeat: {}", ex.getMessage()); - return null; - }); - } - - /** - * Stops the heartbeat. - */ - private void stopHeartbeat() { - if (heartbeatExecutor != null && !heartbeatExecutor.isShutdown()) { - heartbeatExecutor.shutdownNow(); - heartbeatExecutor = null; - } - } - - /** - * Notifies all registered message listeners with the received message. - * Any exceptions thrown by listeners are caught and logged to prevent - * them from affecting other listeners or the WebSocket connection. - * - * @param message The message received from the WebSocket server. - */ - private void notifyMessageListeners(String message) { - for (Consumer listener : messageListeners) { - try { - listener.accept(message); - } - catch (Exception e) { - LOG.error("Error in message listener", e); - } - } - } - - /** - * Notifies all registered close listeners that the WebSocket connection has closed. - * Any exceptions thrown by listeners are caught and logged to prevent - * them from affecting other listeners. - */ - private void notifyCloseListeners() { - for (Runnable listener : closeListeners) { - try { - listener.run(); - } - catch (Exception e) { - LOG.error("Error in close listener", e); - } - } - } - - /** - * Notifies all registered error listeners about a WebSocket error. - * Any exceptions thrown by listeners are caught and logged to prevent - * them from affecting other listeners. - * - * @param error The error that occurred during WebSocket communication. - */ - private void notifyErrorListeners(Throwable error) { - for (Consumer listener : errorListeners) { - try { - listener.accept(error); - } - catch (Exception e) { - LOG.error("Error in error listener", e); - } - } - } - - - - /** - * WebSocket listener implementation. - */ - private class WebSocketListener implements WebSocket.Listener { - - private final StringBuilder messageBuilder = new StringBuilder(); - - - @Override - public void onOpen(WebSocket webSocket) { - LOG.debug("WebSocket connection opened"); - WebSocket.Listener.super.onOpen(webSocket); - } - - @Override - public CompletionStage onText(WebSocket webSocket, CharSequence data, boolean last) { - messageBuilder.append(data); - - if (last) { - String message = messageBuilder.toString(); - messageBuilder.setLength(0); - - LOG.debug("Received message: {}", message); - notifyMessageListeners(message); - } - - return WebSocket.Listener.super.onText(webSocket, data, last); - } - - @Override - public CompletionStage onBinary(WebSocket webSocket, ByteBuffer data, boolean last) { - LOG.debug("Received binary data, size: {}", data.remaining()); - return WebSocket.Listener.super.onBinary(webSocket, data, last); - } - - @Override - public CompletionStage onPing(WebSocket webSocket, ByteBuffer message) { - LOG.debug("Received ping"); - return WebSocket.Listener.super.onPing(webSocket, message); - } - - @Override - public CompletionStage onPong(WebSocket webSocket, ByteBuffer message) { - LOG.debug("Received pong"); - return WebSocket.Listener.super.onPong(webSocket, message); - } - - @Override - public CompletionStage onClose(WebSocket webSocket, int statusCode, String reason) { - LOG.info("WebSocket connection closed: {} - {}", statusCode, reason); - connected = false; - WebSocketClient.this.webSocket = null; - stopHeartbeat(); - notifyCloseListeners(); - return WebSocket.Listener.super.onClose(webSocket, statusCode, reason); - } - - @Override - public void onError(WebSocket webSocket, Throwable error) { - LOG.error("WebSocket error", error); - notifyErrorListeners(error); - WebSocket.Listener.super.onError(webSocket, error); - } - } - - - - /** - * Utility class to create an SSL context that trusts all certificates. - * This is useful for development with self-signed certificates. - */ - private static class TrustAllCertificates { - - public static javax.net.ssl.SSLContext createSslContext() { - try { - javax.net.ssl.SSLContext sslContext = javax.net.ssl.SSLContext.getInstance("TLS"); - sslContext.init(null, new javax.net.ssl.TrustManager[] { - new javax.net.ssl.X509TrustManager() { - public java.security.cert.X509Certificate[] getAcceptedIssuers() { - return new java.security.cert.X509Certificate[0]; - } - - public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) { - } - - public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) { - } - } - }, new java.security.SecureRandom()); - - return sslContext; - } - catch (Exception e) { - throw new RuntimeException("Failed to create SSL context", e); - } - } - } -} diff --git a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/connection/PeerConnectionManager.java b/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/connection/PeerConnectionManager.java deleted file mode 100644 index 8880298..0000000 --- a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/connection/PeerConnectionManager.java +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright 2025 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.examples.web.connection; - -import java.util.List; -import java.util.function.Consumer; - -import dev.onvoid.webrtc.CreateSessionDescriptionObserver; -import dev.onvoid.webrtc.PeerConnectionFactory; -import dev.onvoid.webrtc.PeerConnectionObserver; -import dev.onvoid.webrtc.RTCAnswerOptions; -import dev.onvoid.webrtc.RTCConfiguration; -import dev.onvoid.webrtc.RTCDataChannel; -import dev.onvoid.webrtc.RTCIceCandidate; -import dev.onvoid.webrtc.RTCIceConnectionState; -import dev.onvoid.webrtc.RTCIceGatheringState; -import dev.onvoid.webrtc.RTCIceServer; -import dev.onvoid.webrtc.RTCOfferOptions; -import dev.onvoid.webrtc.RTCPeerConnection; -import dev.onvoid.webrtc.RTCPeerConnectionState; -import dev.onvoid.webrtc.RTCSdpType; -import dev.onvoid.webrtc.RTCSessionDescription; -import dev.onvoid.webrtc.RTCSignalingState; -import dev.onvoid.webrtc.SetSessionDescriptionObserver; -import dev.onvoid.webrtc.examples.web.model.IceCandidateMessage; -import dev.onvoid.webrtc.examples.web.model.SessionDescriptionMessage; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Manages WebRTC peer connections, including creation, configuration, - * and session description handling. Also handles signaling messages related to - * peer connections such as offers, answers, and ICE candidates. - * - * @author Alex Andres - */ -public class PeerConnectionManager implements PeerConnectionSignalingHandler { - - private static final Logger LOG = LoggerFactory.getLogger(PeerConnectionManager.class); - - private final PeerConnectionFactory factory; - private final RTCPeerConnection peerConnection; - - private Consumer onLocalDescriptionCreated; - private Consumer onIceCandidateGenerated; - - private boolean isInitiator = false; - - - /** - * Creates a new PeerConnectionManager. - */ - public PeerConnectionManager() { - factory = new PeerConnectionFactory(); - - // Create peer connection with default configuration. - RTCIceServer iceServer = new RTCIceServer(); - iceServer.urls.add("stun:stun.l.google.com:19302"); - - RTCConfiguration config = new RTCConfiguration(); - config.iceServers.add(iceServer); - - peerConnection = factory.createPeerConnection(config, new PeerConnectionObserverImpl()); - - LOG.info("PeerConnectionManager created"); - } - - /** - * Closes the peer connection. - */ - public void close() { - if (peerConnection != null) { - peerConnection.close(); - } - - if (factory != null) { - factory.dispose(); - } - - LOG.info("Peer connection closed"); - } - - /** - * Creates an offer to initiate a connection. - */ - public void createOffer() { - RTCOfferOptions options = new RTCOfferOptions(); - - peerConnection.createOffer(options, new CreateSessionDescriptionObserver() { - @Override - public void onSuccess(RTCSessionDescription sdp) { - setLocalDescription(sdp); - } - - @Override - public void onFailure(String error) { - LOG.error("Failed to create offer: {}", error); - } - }); - } - - /** - * Creates an answer in response to an offer. - */ - public void createAnswer() { - RTCAnswerOptions options = new RTCAnswerOptions(); - peerConnection.createAnswer(options, new CreateSessionDescriptionObserver() { - @Override - public void onSuccess(RTCSessionDescription answer) { - setLocalDescription(answer); - } - - @Override - public void onFailure(String error) { - LOG.error("Failed to create answer: {}", error); - } - }); - } - - /** - * Sets the local session description. - * - * @param sdp The session description to set. - */ - private void setLocalDescription(RTCSessionDescription sdp) { - peerConnection.setLocalDescription(sdp, new SetSessionDescriptionObserver() { - @Override - public void onSuccess() { - LOG.info("Local description set successfully"); - - if (onLocalDescriptionCreated != null) { - onLocalDescriptionCreated.accept(sdp); - } - } - - @Override - public void onFailure(String error) { - LOG.error("Failed to set local session description: {}", error); - } - }); - } - - /** - * Sets the remote session description. - * - * @param sdp The session description to set. - * @param isOffer True if the description is an offer, false otherwise. - */ - public void setRemoteDescription(RTCSessionDescription sdp, boolean isOffer) { - peerConnection.setRemoteDescription(sdp, new SetSessionDescriptionObserver() { - @Override - public void onSuccess() { - LOG.info("Remote description set successfully"); - - if (isOffer) { - createAnswer(); - } - } - - @Override - public void onFailure(String error) { - LOG.error("Failed to set remote description: {}", error); - } - }); - } - - /** - * Adds an ICE candidate to the peer connection. - * - * @param candidate The ICE candidate to add. - */ - public void addIceCandidate(RTCIceCandidate candidate) { - peerConnection.addIceCandidate(candidate); - LOG.info("Added ICE candidate: {}", candidate.sdp); - } - - /** - * Sets a callback to be invoked when a local session description is created. - * - * @param callback The callback to invoke. - */ - public void setOnLocalDescriptionCreated(Consumer callback) { - this.onLocalDescriptionCreated = callback; - } - - /** - * Sets a callback to be invoked when an ICE candidate is generated. - * - * @param callback The callback to invoke. - */ - public void setOnIceCandidateGenerated(Consumer callback) { - this.onIceCandidateGenerated = callback; - } - - /** - * Sets whether this peer is the initiator of the connection. - * - * @param isInitiator true if this peer is the initiator, false otherwise. - */ - public void setInitiator(boolean isInitiator) { - this.isInitiator = isInitiator; - } - - /** - * Gets whether this peer is the initiator of the connection. - * - * @return true if this peer is the initiator, false otherwise. - */ - public boolean isInitiator() { - return isInitiator; - } - - @Override - public void handleOffer(SessionDescriptionMessage message) { - LOG.info("Received offer"); - - try { - String sdpString = message.getSdp(); - String fromPeer = message.getFrom(); - - LOG.info("Parsed offer from: {}", fromPeer); - - // Create remote session description. - RTCSessionDescription sdp = new RTCSessionDescription(RTCSdpType.OFFER, sdpString); - - // Set remote description and create answer - setRemoteDescription(sdp, true); - } - catch (Exception e) { - LOG.error("Error parsing offer JSON", e); - } - } - - @Override - public void handleAnswer(SessionDescriptionMessage message) { - LOG.info("Received answer"); - - try { - String sdpString = message.getSdp(); - - LOG.info("Successfully parsed answer JSON"); - - // Create remote session description. - RTCSessionDescription sdp = new RTCSessionDescription(RTCSdpType.ANSWER, sdpString); - - // Set remote description - setRemoteDescription(sdp, false); - } - catch (Exception e) { - LOG.error("Error parsing answer JSON", e); - } - } - - @Override - public void handleCandidate(IceCandidateMessage message) { - LOG.info("Received ICE candidate"); - - try { - IceCandidateMessage.IceCandidateData data = message.getData(); - String sdpMid = data.getSdpMid(); - int sdpMLineIndex = data.getSdpMLineIndex(); - String candidate = data.getCandidate(); - - LOG.info("Successfully parsed ICE candidate JSON"); - - RTCIceCandidate iceCandidate = new RTCIceCandidate(sdpMid, sdpMLineIndex, candidate); - addIceCandidate(iceCandidate); - } - catch (Exception e) { - LOG.error("Error parsing ICE candidate JSON", e); - } - } - - - - /** - * Implementation of PeerConnectionObserver to handle WebRTC events. - */ - private class PeerConnectionObserverImpl implements PeerConnectionObserver { - - @Override - public void onIceCandidate(RTCIceCandidate candidate) { - LOG.info("New ICE candidate: {}", candidate.sdp); - - if (onIceCandidateGenerated != null) { - onIceCandidateGenerated.accept(candidate); - } - } - - @Override - public void onConnectionChange(RTCPeerConnectionState state) { - LOG.info("Connection state changed to: {}", state); - } - - @Override - public void onIceConnectionChange(RTCIceConnectionState state) { - LOG.info("ICE connection state changed to: {}", state); - } - - @Override - public void onIceGatheringChange(RTCIceGatheringState state) { - LOG.info("ICE gathering state changed to: {}", state); - } - - @Override - public void onSignalingChange(RTCSignalingState state) { - LOG.info("Signaling state changed to: {}", state); - } - - @Override - public void onDataChannel(RTCDataChannel dataChannel) { - LOG.info("Data channel created: {}", dataChannel.getLabel()); - } - - @Override - public void onRenegotiationNeeded() { - LOG.info("Renegotiation needed"); - createOffer(); - } - } -} \ No newline at end of file diff --git a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/connection/PeerConnectionSignalingHandler.java b/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/connection/PeerConnectionSignalingHandler.java deleted file mode 100644 index fda95cb..0000000 --- a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/connection/PeerConnectionSignalingHandler.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2025 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.examples.web.connection; - -import dev.onvoid.webrtc.examples.web.model.IceCandidateMessage; -import dev.onvoid.webrtc.examples.web.model.SessionDescriptionMessage; - -/** - * This interface defines methods for processing signaling messages - * directly related to WebRTC peer connections. - * - * @author Alex Andres - */ -public interface PeerConnectionSignalingHandler { - - /** - * Handles an incoming offer from a remote peer. - * - * @param message The session description message containing the offer. - */ - void handleOffer(SessionDescriptionMessage message); - - /** - * Handles an incoming answer from a remote peer. - * - * @param message The session description message containing the answer. - */ - void handleAnswer(SessionDescriptionMessage message); - - /** - * Handles an incoming ICE candidate from a remote peer. - * - * @param message The message containing the ICE candidate. - */ - void handleCandidate(IceCandidateMessage message); - -} \ No newline at end of file diff --git a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/model/IceCandidateMessage.java b/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/model/IceCandidateMessage.java deleted file mode 100644 index d53f366..0000000 --- a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/model/IceCandidateMessage.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright 2025 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.examples.web.model; - -/** - * Represents an ICE candidate message used in WebRTC signaling. - *

    - * This class is used to exchange ICE candidates between peers during - * the connection establishment process. - *

    - * - * @author Alex Andres - */ -public class IceCandidateMessage extends SignalingMessage { - - private IceCandidateData data; - - - /** - * Default constructor required for JSON deserialization. - */ - public IceCandidateMessage() { - super(MessageType.ICE_CANDIDATE.getValue()); - } - - /** - * Creates a new IceCandidateMessage with the specified sender and recipient. - * - * @param from the sender ID. - * @param to the recipient ID. - */ - public IceCandidateMessage(String from, String to) { - super(MessageType.ICE_CANDIDATE.getValue(), from, to); - - data = new IceCandidateData(); - } - - /** - * Creates a new IceCandidateMessage with the specified sender, recipient, and candidate information. - * - * @param from the sender ID. - * @param to the recipient ID. - * @param candidate the candidate string. - * @param sdpMid the SDP mid. - * @param sdpMLineIndex the SDP mline index. - */ - public IceCandidateMessage(String from, String to, String candidate, String sdpMid, int sdpMLineIndex) { - super(MessageType.ICE_CANDIDATE.getValue(), from, to); - - data = new IceCandidateData(candidate, sdpMid, sdpMLineIndex); - } - - /** - * Gets the ICE candidate data. - * - * @return the ICE candidate data. - */ - public IceCandidateData getData() { - return data; - } - - /** - * Sets the ICE candidate data. - * - * @param data the ICE candidate data. - */ - public void setData(IceCandidateData data) { - this.data = data; - } - - - - /** - * Inner class representing the data payload of an ICE candidate message. - */ - public static class IceCandidateData { - - private String candidate; - private String sdpMid; - private int sdpMLineIndex; - - - /** - * Default constructor required for JSON deserialization. - */ - public IceCandidateData() { - } - - /** - * Creates a new IceCandidateData with the specified candidate information. - * - * @param candidate the candidate string. - * @param sdpMid the SDP mid. - * @param sdpMLineIndex the SDP mline index. - */ - public IceCandidateData(String candidate, String sdpMid, int sdpMLineIndex) { - this.candidate = candidate; - this.sdpMid = sdpMid; - this.sdpMLineIndex = sdpMLineIndex; - } - - /** - * Gets the candidate string. - * - * @return the candidate string. - */ - public String getCandidate() { - return candidate; - } - - /** - * Sets the candidate string. - * - * @param candidate the candidate string. - */ - public void setCandidate(String candidate) { - this.candidate = candidate; - } - - /** - * Gets the SDP mid. - * - * @return the SDP mid. - */ - public String getSdpMid() { - return sdpMid; - } - - /** - * Sets the SDP mid. - * - * @param sdpMid the SDP mid. - */ - public void setSdpMid(String sdpMid) { - this.sdpMid = sdpMid; - } - - /** - * Gets the SDP mline index. - * - * @return the SDP mline index. - */ - public int getSdpMLineIndex() { - return sdpMLineIndex; - } - - /** - * Sets the SDP mline index. - * - * @param sdpMLineIndex the SDP mline index. - */ - public void setSdpMLineIndex(int sdpMLineIndex) { - this.sdpMLineIndex = sdpMLineIndex; - } - } -} \ No newline at end of file diff --git a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/model/JoinMessage.java b/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/model/JoinMessage.java deleted file mode 100644 index 53b2207..0000000 --- a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/model/JoinMessage.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright 2025 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.examples.web.model; - -/** - * Represents a join message used in WebRTC signaling. - * This class is used when a peer wants to join a room or session. - * - * @author Alex Andres - */ -public class JoinMessage extends SignalingMessage { - - private JoinData data; - - - /** - * Default constructor required for JSON deserialization. - */ - public JoinMessage() { - super(MessageType.JOIN.getValue()); - } - - /** - * Creates a new JoinMessage with the specified sender, room, and user information. - * - * @param from the sender ID. - * @param room the room to join. - * @param userName the user's name. - */ - public JoinMessage(String from, String room, String userName) { - super(MessageType.JOIN.getValue(), from, null); - - data = new JoinData(room, new UserInfo(userName, from)); - } - - /** - * Gets the join data. - * - * @return the join data. - */ - public JoinData getData() { - return data; - } - - /** - * Sets the join data. - * - * @param data the join data. - */ - public void setData(JoinData data) { - this.data = data; - } - - - - /** - * Inner class representing the data payload of a join message. - */ - public static class JoinData { - - private String room; - private UserInfo userInfo; - - - /** - * Default constructor required for JSON deserialization. - */ - public JoinData() { - } - - /** - * Creates a new JoinData with the specified room. - * - * @param room the room to join - */ - public JoinData(String room) { - this.room = room; - } - - /** - * Creates a new JoinData with the specified room and user information. - * - * @param room the room to join - * @param userInfo the user information - */ - public JoinData(String room, UserInfo userInfo) { - this.room = room; - this.userInfo = userInfo; - } - - /** - * Gets the room. - * - * @return the room - */ - public String getRoom() { - return room; - } - - /** - * Sets the room. - * - * @param room the room - */ - public void setRoom(String room) { - this.room = room; - } - - /** - * Gets the user information. - * - * @return the user information - */ - public UserInfo getUserInfo() { - return userInfo; - } - - /** - * Sets the user information. - * - * @param userInfo the user information - */ - public void setUserInfo(UserInfo userInfo) { - this.userInfo = userInfo; - } - } - - - - /** - * Inner class representing user information. - */ - public static class UserInfo { - - private String userId; - - private String name; - - - /** - * Default constructor required for JSON deserialization. - */ - public UserInfo() { - } - - /** - * Creates a new UserInfo with the specified name and avatar. - * - * @param name the user's name. - * @param userId the user's ID. - */ - public UserInfo(String name, String userId) { - this.name = name; - this.userId = userId; - } - - /** - * Gets the user's name. - * - * @return the user's name. - */ - public String getName() { - return name; - } - - /** - * Sets the user's name. - * - * @param name the user's name. - */ - public void setName(String name) { - this.name = name; - } - - /** - * Gets the user's ID. - * - * @return the user's ID. - */ - public String getUserId() { - return userId; - } - - /** - * Sets the user's ID. - * - * @param userId the user's ID. - */ - public void setUserId(String userId) { - this.userId = userId; - } - } -} \ No newline at end of file diff --git a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/model/LeaveMessage.java b/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/model/LeaveMessage.java deleted file mode 100644 index 6b5cf1c..0000000 --- a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/model/LeaveMessage.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2025 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.examples.web.model; - -/** - * Represents a message indicating that a user is leaving a room. - * This class is used when a peer leaves a room or session. - * - * @author Alex Andres - */ -public class LeaveMessage extends SignalingMessage { - - /** - * Constructs a new leave message with default values. - */ - public LeaveMessage() { - super(MessageType.LEAVE.getValue()); - } - -} diff --git a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/model/MessageType.java b/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/model/MessageType.java deleted file mode 100644 index b4b8f2c..0000000 --- a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/model/MessageType.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2025 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.examples.web.model; - -/** - * Represents the types of messages exchanged during WebRTC signaling. - * Each message type corresponds to a specific action or state in the WebRTC connection process. - * - * @author Alex Andres - */ -public enum MessageType { - - /** WebRTC offer message containing session description. */ - OFFER("offer"), - - /** WebRTC answer message containing session description. */ - ANSWER("answer"), - - /** ICE candidate information for establishing peer connections. */ - ICE_CANDIDATE("ice-candidate"), - - /** Message indicating a peer joining the signaling session. */ - JOIN("join"), - - /** Message indicating a peer leaving the signaling session. */ - LEAVE("leave"), - - /** Heartbeat message to maintain connection. */ - HEARTBEAT("heartbeat"), - - /** Acknowledgment response to a heartbeat message. */ - HEARTBEAT_ACK("heartbeat-ack"), - - /** Fallback type for unrecognized messages. */ - UNKNOWN(""); - - /** The string representation of the message type. */ - private final String value; - - - /** - * Constructs a message type with the specified string value. - * - * @param value The string representation of this message type - */ - MessageType(String value) { - this.value = value; - } - - /** - * Returns the string representation of this message type. - * - * @return The string value of this message type - */ - public String getValue() { - return value; - } - - /** - * Finds and returns the message type enum constant that matches the given string. - * - * @param text The string to convert to a message type - * @return The matching message type, or UNKNOWN if no match is found - */ - public static MessageType fromString(String text) { - for (MessageType type : MessageType.values()) { - if (type.value.equals(text)) { - return type; - } - } - return UNKNOWN; - } -} diff --git a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/model/SessionDescriptionMessage.java b/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/model/SessionDescriptionMessage.java deleted file mode 100644 index 08e529a..0000000 --- a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/model/SessionDescriptionMessage.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2025 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.examples.web.model; - -/** - * Represents a session description message used in WebRTC signaling. - *

    - * This class is used for both offer and answer messages, which contain - * Session Description Protocol (SDP) information. - *

    - * - * @author Alex Andres - */ -public class SessionDescriptionMessage extends SignalingMessage { - - private SessionDescriptionData data; - - - /** - * Default constructor required for JSON deserialization. - */ - public SessionDescriptionMessage() { - super(); - } - - /** - * Creates a new SessionDescriptionMessage with the specified type, sender, recipient, and SDP. - * - * @param type the message type (either "offer" or "answer"). - * @param from the sender ID. - * @param to the recipient ID. - * @param sdp the SDP string. - */ - public SessionDescriptionMessage(String type, String from, String to, String sdp) { - super(type, from, to); - - data = new SessionDescriptionData(sdp); - } - - /** - * Gets the session description data. - * - * @return the session description data. - */ - public SessionDescriptionData getData() { - return data; - } - - /** - * Sets the session description data. - * - * @param data the session description data. - */ - public void setData(SessionDescriptionData data) { - this.data = data; - } - - /** - * Sets the SDP string. - * - * @param sdp the SDP string. - */ - public void setSdp(String sdp) { - if (data == null) { - data = new SessionDescriptionData(); - } - data.setSdp(sdp); - } - - /** - * Gets the SDP string. - * - * @return the SDP string. - */ - public String getSdp() { - return data != null ? data.getSdp() : null; - } - - - - /** - * Inner class representing the data payload of a session description message. - */ - public static class SessionDescriptionData { - - private String sdp; - - - /** - * Default constructor required for JSON deserialization. - */ - public SessionDescriptionData() { - } - - /** - * Creates a new SessionDescriptionData with the specified SDP. - * - * @param sdp the SDP string. - */ - public SessionDescriptionData(String sdp) { - this.sdp = sdp; - } - - /** - * Gets the SDP string. - * - * @return the SDP string. - */ - public String getSdp() { - return sdp; - } - - /** - * Sets the SDP string. - * - * @param sdp the SDP string. - */ - public void setSdp(String sdp) { - this.sdp = sdp; - } - } -} \ No newline at end of file diff --git a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/model/SignalingMessage.java b/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/model/SignalingMessage.java deleted file mode 100644 index f09d7fc..0000000 --- a/webrtc-examples/src/main/java/dev/onvoid/webrtc/examples/web/model/SignalingMessage.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2025 Alex Andres - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.onvoid.webrtc.examples.web.model; - -/** - * Base class for all signaling messages. - *

    - * This class represents the common structure of all messages exchanged - * during WebRTC signaling. Specific message types extend this class - * and add their own data payload. - *

    - * - * @author Alex Andres - */ -public class SignalingMessage { - - private String type; - private String from; - private String to; - - - /** - * Default constructor required for JSON deserialization. - */ - public SignalingMessage() { - } - - /** - * Creates a new SignalingMessage with the specified type. - * - * @param type the message type. - */ - public SignalingMessage(String type) { - this.type = type; - } - - /** - * Creates a new SignalingMessage with the specified type, sender, and recipient. - * - * @param type the message type. - * @param from the sender ID. - * @param to the recipient ID. - */ - public SignalingMessage(String type, String from, String to) { - this.type = type; - this.from = from; - this.to = to; - } - - /** - * Gets the message type. - * - * @return the message type. - */ - public String getType() { - return type; - } - - /** - * Sets the message type. - * - * @param type the message type. - */ - public void setType(String type) { - this.type = type; - } - - /** - * Gets the sender ID. - * - * @return the sender ID. - */ - public String getFrom() { - return from; - } - - /** - * Sets the sender ID. - * - * @param from the sender ID. - */ - public void setFrom(String from) { - this.from = from; - } - - /** - * Gets the recipient ID. - * - * @return the recipient ID. - */ - public String getTo() { - return to; - } - - /** - * Sets the recipient ID. - * - * @param to the recipient ID. - */ - public void setTo(String to) { - this.to = to; - } -} \ No newline at end of file diff --git a/webrtc-examples/src/main/java/module-info.java b/webrtc-examples/src/main/java/module-info.java deleted file mode 100644 index 4c3b296..0000000 --- a/webrtc-examples/src/main/java/module-info.java +++ /dev/null @@ -1,13 +0,0 @@ -module webrtc.java.examples { - - requires com.fasterxml.jackson.databind; - requires java.logging; - requires java.net.http; - requires org.eclipse.jetty.server; - requires org.eclipse.jetty.websocket.server; - requires webrtc.java; - - exports dev.onvoid.webrtc.examples.web.client; - exports dev.onvoid.webrtc.examples.web.model; - -} \ No newline at end of file diff --git a/webrtc-examples/src/main/resources/keystore.p12 b/webrtc-examples/src/main/resources/keystore.p12 deleted file mode 100644 index b655bbacf920624e3fe23f3addeb54714029f630..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2723 zcmai$X*3iH8^>p}jIA1}Y{l4hhcVY0x<`86NCJlyD^xbtAeO-mWCP|B zIP@R{4((s~B9Z`k^>4+ROMpE4h0;Mlz^|3^Zv#YPe+L$BBnGMQZ{$LXLymJHsZRP& zKGK)1Gz_nxz7K*x>;NPeEBpVhf}kt_q%bS=daMD^4GaOwLXMLZRWMv16!qD{3rk6g zO=s>AAR?zR{NQ5m)~0B4z;sjyc6SPAYL`&rh5bzaphn$b@J!s)9#CPlY^vNI*_Uyt zZ3Au{>si!KE)3XMLWt~R2SVxPG_t@kO*vB(>ZR^W|F7sHfmQM+zEH8F}H&55K%92RpvcKXTq3S#qT`B1xW-mD3 zI{5L!D&MEJ{vy>xKW=ka%)-f!kuiT|L&zF58NV zzB@2OQJcjjBdNj|OHNl$NCmJ^Sudh*Fh(Y%#3+Vy)BE}4RFF0^$!nFWRMANQ>F)IZP0;jD5TybB_=
    YCripqPKpQoM>TB6N3#|n15HRX!m z`o}98JZ}KJPxEi)Rloh@lX7r8A3E=iW5&gZ`l8nqjhV}f!FFKrqx$_zGVeA= zm9F+MJ1gTMe^MPwd~(ylkFG5jE{MHpm|5H2xPz-RG>$*EnL0h?ji~sMBD7vg zq@8G~4ima2sNY#WMALJ@B+2f9J8w)zxSQ(-xquLR6*4uRu_dfd;0@8ALqAlP(ZKA+T3fcJf%0c9Yp*ws&9J&?`9H@ zzwkv&_cP`|pK?RE>K`Gk`8Q1Y-Lc)2R)Y?`mSXtJ@8%bbE{Oz58M8*;ZA+Ut}!nc2oFDvK&9mmB11pO-2 zenF-G5|<;Fx--=%edJ3xMy$+bcjiCEh0iYZ)!vQ+y)%{9<=1qahY%oxp%T>SA^w|V z_YNP#g>^$!dn%s5*X=D|7s-mudQ()o*)McG9{;A4k0+68&Lj(bzT%MaT;%2rTa8s< zs<$@N3>4N{13F(S2QZg;A;>WPA$6q3Wx1IcYY+ze7Ry~J)oHlyzMy52!ws|299n97 zrrovh_0d^Jo<$4E#YjeZsC}5#%JJdkZZ&HkIa@qa)Ticy&0gvkPhsnmsnBlN#NI$lju@r9$G7BY>y>rkO(+<-a?~G&h#k`T zR#IUrqvZP^%N9;B;N=C+Lz-I*bhp=pjom|Qq{V|+>~bf>%d!d1_ypK2)LMlSzXFROc$iM(YSI4h@P*s({yh+KZOgsTrQNJcKfevZwxN$zWIquXD60))i(Lss4QL^N|Gln$=jxDQL9)C zif)48?Q(Z1$NHbU|Db!#Xlt>#bG;d1{Zk{>;!Zmse3a%-KFMdMq5fm&>CL?4Yovip z6hRXZ+Cpf2`a|s_Hg3XW!zf0SttP4RMEbW7^5?R6gV}oQ(Ph{TP?$Zf<%uqVqS$;Fz0Yuc5=yuh2 zRM0nK+ENG<;NU4i{;}fcviJlxB5`qw=TmWo_V{>RaFAeqOk*XsVty8Wv8P3U%5n%K z&J4V?mb$;h%eGG;4eN_r2bW0i(bOInS^Twy$cy~Q=IOk`VII^g5*;cZdIaYywqL2w z>y$*BcUS4O_zI0^*Lm{T%!YQ5nY?mhWg};kJ*UuEXnKhg;#i8+p)-uA=kk`XYGbuu zed`rVQ zM}`RmeO#JGC&35Te2i0=!JAh6uwKWpTS);F;!m4tI5!}_5;S^HDR`;mD(TB#!l&=R z7kTY11`l3%;bLNXLDq+F&Ky%-AKlGXkU)z47A=%d;S}T~+}muk4Cu0E;a@h~KBD6h z{-*gG5{* { - if (this.onTrackCallback) { - this.onTrackCallback(event); - } - }; - - this.peerConnection.onicecandidate = (event) => { - if (event.candidate && this.onIceCandidateCallback) { - const candidate = { - type: "ice-candidate", - from: this.getUserId(), - to: this.getRemotePeerId(), - data: { - candidate: event.candidate.candidate, - sdpMid: event.candidate.sdpMid, - sdpMLineIndex: event.candidate.sdpMLineIndex - } - }; - this.onIceCandidateCallback(candidate); - } - }; - - this.peerConnection.oniceconnectionstatechange = () => { - if (this.onIceConnectionStateChangeCallback) { - this.onIceConnectionStateChangeCallback(this.peerConnection.iceConnectionState); - } - }; - - this.peerConnection.onconnectionstatechange = () => { - if (this.onConnectionStateChangeCallback) { - this.onConnectionStateChangeCallback(this.peerConnection.connectionState); - } - }; - } - - async addLocalMedia() { - try { - this.localStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true }); - this.localStream.getTracks().forEach(track => { - this.peerConnection.addTrack(track, this.localStream); - }); - return true; - } - catch (error) { - console.error("Error accessing media devices:", error); - return false; - } - } - - async createOffer() { - try { - const offer = await this.peerConnection.createOffer(); - await this.peerConnection.setLocalDescription(offer); - return { - type: "offer", - from: this.getUserId(), - to: this.getRemotePeerId(), - data: { - sdp: this.peerConnection.localDescription.sdp - } - }; - } - catch (error) { - console.error("Error creating offer:", error); - throw error; - } - } - - async handleOffer(message) { - try { - // Extract SDP from the data object in the message format - const sdp = message.data.sdp.replace(/\\n/g, '\n'); - const sessionDescription = new RTCSessionDescription({ - type: "offer", - sdp: sdp - }); - await this.peerConnection.setRemoteDescription(sessionDescription); - return true; - } - catch (error) { - console.error("Error setting remote description for offer:", error); - throw error; - } - } - - async createAnswer() { - try { - const answer = await this.peerConnection.createAnswer(); - await this.peerConnection.setLocalDescription(answer); - - console.log("Local answer:", answer); - console.log("Local description:", this.peerConnection.localDescription); - - return { - type: "answer", - from: this.getUserId(), - to: this.getRemotePeerId(), - data: { - sdp: this.peerConnection.localDescription.sdp - } - }; - } - catch (error) { - console.error("Error creating answer:", error); - throw error; - } - } - - async handleAnswer(message) { - try { - // Extract SDP from the data object in the new message format - const sdp = message.data.sdp.replace(/\\n/g, '\n'); - const sessionDescription = new RTCSessionDescription({ - type: "answer", - sdp: sdp - }); - await this.peerConnection.setRemoteDescription(sessionDescription); - } - catch (error) { - console.error("Error setting remote description:", error); - throw error; - } - } - - async addIceCandidate(message) { - try { - // Extract candidate information from the data object in the new message format - const candidate = new RTCIceCandidate({ - sdpMid: message.data.sdpMid, - sdpMLineIndex: message.data.sdpMLineIndex, - candidate: message.data.candidate - }); - await this.peerConnection.addIceCandidate(candidate); - - console.log('ICE candidate added successfully'); - } - catch (error) { - console.error('Error adding ICE candidate:', error); - throw error; - } - } - - close() { - if (this.localStream) { - this.localStream.getTracks().forEach(track => track.stop()); - this.localStream = null; - } - - if (this.peerConnection) { - this.peerConnection.close(); - this.peerConnection = null; - } - } -} - -export { PeerConnectionManager }; \ No newline at end of file diff --git a/webrtc-examples/src/main/resources/web/SignalingChannel.js b/webrtc-examples/src/main/resources/web/SignalingChannel.js deleted file mode 100644 index cdcb128..0000000 --- a/webrtc-examples/src/main/resources/web/SignalingChannel.js +++ /dev/null @@ -1,142 +0,0 @@ -/** - * SignalingChannel handles WebSocket communication for WebRTC signaling. - * It includes a heartbeat mechanism to keep the connection alive and detect disconnections early. - */ -class SignalingChannel { - - /** - * Creates a new SignalingChannel instance. - * - * @param {string} serverUrl - The WebSocket server URL. - * @param {function} onMessage - Callback for received messages. - * @param {function} onOpen - Callback for connection open. - * @param {function} onClose - Callback for connection close. - * @param {function} onError - Callback for connection errors. - */ - constructor(serverUrl, onOpen, onClose, onMessage, onError) { - this.serverUrl = serverUrl; - this.onMessageCallback = onMessage; - this.onOpenCallback = onOpen; - this.onCloseCallback = onClose; - this.onErrorCallback = onError; - this.socket = null; - this.heartbeatInterval = 10000; // 10 seconds - this.heartbeatTimer = null; - } - - /** - * Establishes a WebSocket connection to the signaling server. - * Automatically starts the heartbeat mechanism when connected. - */ - connect() { - this.socket = new WebSocket(this.serverUrl, "ws-signaling"); - - this.socket.onopen = () => { - this.startHeartbeat(); - - if (this.onOpenCallback) { - this.onOpenCallback(); - } - }; - - this.socket.onmessage = (event) => { - console.log("Received message:", event.data); - const message = JSON.parse(event.data); - - // Handle heartbeat response. - if (message.type === "heartbeat-ack") { - // Heartbeat acknowledged. - return; - } - - if (this.onMessageCallback) { - this.onMessageCallback(message); - } - }; - - this.socket.onclose = () => { - this.stopHeartbeat(); - - if (this.onCloseCallback) { - this.onCloseCallback(); - } - }; - - this.socket.onerror = (error) => { - this.stopHeartbeat(); - - if (this.onErrorCallback) { - this.onErrorCallback(error); - } - }; - } - - /** - * Starts the heartbeat mechanism to keep the WebSocket connection alive. - * Sends a heartbeat message every this.heartbeatInterval millisecond. - */ - startHeartbeat() { - // Clear any existing timer. - this.stopHeartbeat(); - - this.heartbeatTimer = setInterval(() => { - if (this.isConnected()) { - this.send({ - type: "heartbeat", - from: this.getUserId() - }); - } - else { - this.stopHeartbeat(); - } - }, this.heartbeatInterval); - } - - // Helper method to get the current user ID - getUserId() { - // In a real application, this would be a unique identifier for the user - return "web-client"; - } - - /** - * Stops the heartbeat mechanism. - * Called automatically when the connection is closed or on error. - */ - stopHeartbeat() { - if (this.heartbeatTimer) { - clearInterval(this.heartbeatTimer); - this.heartbeatTimer = null; - } - } - - send(message) { - if (this.isConnected()) { - this.socket.send(JSON.stringify(message)); - } - else { - console.error("WebSocket is not open. Cannot send message:", message); - } - } - - /** - * Closes the WebSocket connection and stops the heartbeat mechanism. - */ - close() { - this.stopHeartbeat(); - - if (this.isConnected()) { - this.socket.close(); - } - } - - /** - * Checks if the WebSocket connection is currently open. - * - * @returns {boolean} True if the connection is open. - */ - isConnected() { - return this.socket && this.socket.readyState === WebSocket.OPEN; - } -} - -export { SignalingChannel }; \ No newline at end of file diff --git a/webrtc-examples/src/main/resources/web/WebRTCClient.js b/webrtc-examples/src/main/resources/web/WebRTCClient.js deleted file mode 100644 index 4bc5a68..0000000 --- a/webrtc-examples/src/main/resources/web/WebRTCClient.js +++ /dev/null @@ -1,332 +0,0 @@ -import { SignalingChannel } from './SignalingChannel.js'; -import { PeerConnectionManager } from './PeerConnectionManager.js'; - -class WebRTCClient { - - constructor() { - // Configuration. - this.serverUrl = "wss://localhost:8443/ws"; - this.iceServers = [ - { urls: "stun:stun.l.google.com:19302" } - ]; - - // DOM elements. - this.remoteVideo = document.getElementById("remoteVideo"); - this.videoContainer = document.getElementById("videoContainer"); - this.stopButton = document.getElementById("stopButton"); - this.statusElement = document.getElementById("status"); - this.participantsList = document.getElementById("participantsList"); - - // Initialize components. - this.signalingChannel = null; - this.peerConnectionManager = null; - this.participants = new Map(); - - // Set up event listeners. - this.stopButton.addEventListener("click", () => this.disconnect()); - - // Set the initial status. - this.setStatus("Click \"Start Connection\" to begin"); - - this.connect(); - } - - setStatus(status) { - this.statusElement.textContent = status; - - console.log(status); - } - - connect() { - this.setStatus("Connecting to the signaling server..."); - - // Initialize signaling channel. - this.signalingChannel = new SignalingChannel( - this.serverUrl, - () => this.handleSignalingOpen(), - () => this.handleSignalingClose(), - (message) => this.handleSignalingMessage(message), - (error) => this.handleSignalingError(error) - ); - - // Connect to the signaling server. - this.signalingChannel.connect(); - } - - disconnect() { - this.setStatus("Closing connection"); - - // Close peer connection - if (this.peerConnectionManager) { - this.peerConnectionManager.close(); - this.peerConnectionManager = null; - } - - // Close signaling channel - if (this.signalingChannel) { - this.signalingChannel.close(); - this.signalingChannel = null; - } - - // Clear remote video - if (this.remoteVideo.srcObject) { - this.remoteVideo.srcObject.getTracks().forEach(track => track.stop()); - this.remoteVideo.srcObject = null; - } - - // Hide video container - this.videoContainer.style.display = 'none'; - - // Clear participants list - this.participants.clear(); - this.updateParticipantsList(); - - // Update UI - this.stopButton.disabled = true; - this.setStatus("Connection closed"); - } - - joinRoom(roomName) { - // First, send a join message to the room. - const joinMessage = { - type: "join", - from: this.peerConnectionManager.getUserId(), - data: { - room: roomName, - userInfo: { - name: "Web Client" - } - } - }; - this.signalingChannel.send(joinMessage); - this.setStatus('Joining room: default-room'); - } - - handleSignalingOpen() { - this.setStatus("Connected to the signaling server"); - - // Initialize peer connection manager. - this.peerConnectionManager = new PeerConnectionManager( - this.iceServers, - (event) => this.handleTrack(event), - (candidate) => this.handleLocalCandidate(candidate), - (state) => this.handleIceConnectionStateChange(state), - (state) => this.handleConnectionStateChange(state) - ); - - // Add ourselves to the participant list. - const myUserId = this.peerConnectionManager.getUserId(); - this.participants.set(myUserId, { name: "Me (Local)" }); - this.updateParticipantsList(); - - this.joinRoom("default-room"); - - // Update UI. - this.stopButton.disabled = false; - } - - handleSignalingMessage(message) { - switch(message.type) { - case 'answer': - this.handleAnswer(message); - break; - case 'ice-candidate': - this.handleRemoteCandidate(message); - break; - case 'offer': - this.handleOffer(message); - break; - case 'join': - this.handleUserJoined(message); - break; - case 'leave': - this.handleUserLeft(message); - break; - default: - console.log('Unknown message type:', message.type); - } - } - - handleUserJoined(message) { - const userId = message.data.userInfo.userId; - this.setStatus('User joined: ' + userId); - - // Add user to participants map if not already present. - if (!this.participants.has(userId)) { - const userInfo = message.data.userInfo || { userId: userId }; - this.participants.set(userId, userInfo); - - // Update the participant list in the UI. - this.updateParticipantsList(); - } - } - - handleUserLeft(message) { - const userId = message.from; - this.setStatus('User left: ' + userId); - - // Remove user from participants map if present - if (this.participants.has(userId)) { - this.participants.delete(userId); - - // Update the participant list in the UI - this.updateParticipantsList(); - } - } - - async handleOffer(message) { - this.setStatus('Received offer from ' + message.from); - console.log('Received offer:', message); - - // Initialize WebRTC. - this.startWebRTC(); - - try { - // Set the offer to the peer connection. - await this.peerConnectionManager.handleOffer(message); - this.setStatus('Remote offer set successfully, creating answer'); - - // Create and send answer - const answer = await this.peerConnectionManager.createAnswer(); - this.setStatus('Sending answer to ' + message.from); - this.signalingChannel.send(answer); - } - catch (error) { - this.setStatus('Failed to process offer: ' + error); - console.error('Error handling offer:', error); - } - } - - updateParticipantsList() { - // Clear the current list - this.participantsList.innerHTML = ''; - - // Add each participant to the list - this.participants.forEach((userInfo, userId) => { - const listItem = document.createElement('li'); - listItem.textContent = userInfo.name || userId; - listItem.setAttribute('data-user-id', userId); - this.participantsList.appendChild(listItem); - }); - } - - handleSignalingClose() { - this.setStatus('Disconnected from signaling server'); - this.disconnect(); - } - - handleSignalingError(error) { - this.setStatus('Error connecting to signaling server'); - console.error('WebSocket error:', error); - } - - async startWebRTC() { - this.peerConnectionManager.initialize(); - - // Add local media if available - // const mediaAdded = await this.peerConnectionManager.addLocalMedia(); - // if (!mediaAdded) { - // this.setStatus('Failed to access camera/microphone. Creating offer without local media.'); - // } - - // Create and send offer - // try { - // const offer = await this.peerConnectionManager.createOffer(); - // this.setStatus('Sending offer to Java server'); - // this.signalingChannel.send(offer); - // } - // catch (error) { - // this.setStatus('Failed to create offer: ' + error); - // } - } - - handleTrack(event) { - this.setStatus('Received remote track'); - console.log('Track event:', event); - - if (event.streams && event.streams[0]) { - // If remoteVideo already has a srcObject, we need to add the new track to it - // instead of replacing the entire stream. - if (this.remoteVideo.srcObject) { - // Check if this track already exists in the current stream. - const existingTrack = this.remoteVideo.srcObject.getTracks().find( - track => track.id === event.track.id - ); - - // Only add the track if it doesn't already exist. - if (!existingTrack) { - // Add the new track to the existing stream. - this.remoteVideo.srcObject.addTrack(event.track); - this.setStatus(`Added ${event.track.kind} track to existing stream`); - } - } - else { - // First track, set the stream directly. - this.remoteVideo.srcObject = event.streams[0]; - this.setStatus(`Set initial ${event.track.kind} stream`); - } - - // Show the video container when we receive a track. - this.videoContainer.style.display = 'block'; - - // Ensure the video plays. - this.remoteVideo.play().catch(error => { - console.error('Error playing video:', error); - this.setStatus('Error playing video: ' + error.message); - }); - } - else { - console.warn('Received track event without streams'); - this.setStatus('Received track without stream data'); - } - } - - handleLocalCandidate(candidate) { - this.signalingChannel.send(candidate); - } - - handleIceConnectionStateChange(state) { - this.setStatus('ICE connection state: ' + state); - - // Hide video if connection is disconnected, failed, or closed - if (['disconnected', 'failed', 'closed'].includes(state)) { - this.videoContainer.style.display = 'none'; - } - } - - handleConnectionStateChange(state) { - this.setStatus('Connection state: ' + state); - - // Show video only when connected - if (state === 'connected') { - this.videoContainer.style.display = 'block'; - } else if (['disconnected', 'failed', 'closed'].includes(state)) { - this.videoContainer.style.display = 'none'; - } - } - - async handleAnswer(message) { - this.setStatus('Received answer from ' + message.from + ', setting remote description'); - - try { - await this.peerConnectionManager.handleAnswer(message); - this.setStatus('Remote description set successfully'); - } - catch (error) { - this.setStatus('Failed to set remote description: ' + error); - } - } - - async handleRemoteCandidate(message) { - try { - this.setStatus('Received ICE candidate from ' + message.from); - - await this.peerConnectionManager.addIceCandidate(message); - } - catch (error) { - console.error("Error handling remote candidate:", error); - } - } -} - -export { WebRTCClient }; \ No newline at end of file diff --git a/webrtc-examples/src/main/resources/web/index.html b/webrtc-examples/src/main/resources/web/index.html deleted file mode 100644 index 7ba5e44..0000000 --- a/webrtc-examples/src/main/resources/web/index.html +++ /dev/null @@ -1,158 +0,0 @@ - - - - - - WebRTC Java - Browser Demo - - - - - - - -
    - -
    -

    Participants

    -
      - -
    -
    - - -
    - -
    - -
    - - -
    - -
    -
    -
    - - - - - diff --git a/webrtc-examples/src/main/resources/web/main.js b/webrtc-examples/src/main/resources/web/main.js deleted file mode 100644 index 3a456f7..0000000 --- a/webrtc-examples/src/main/resources/web/main.js +++ /dev/null @@ -1,6 +0,0 @@ -import { WebRTCClient } from './WebRTCClient.js'; - -// Initialize the WebRTC client when the page loads -document.addEventListener("DOMContentLoaded", () => { - new WebRTCClient(); -}); \ No newline at end of file diff --git a/webrtc-jni/build.gradle.kts b/webrtc-jni/build.gradle.kts new file mode 100644 index 0000000..c2252d4 --- /dev/null +++ b/webrtc-jni/build.gradle.kts @@ -0,0 +1,127 @@ +import io.github.tomaki19.gradle.cmake.extension.api.CMakeToolchain +import org.gradle.internal.os.OperatingSystem + +plugins { + alias(libs.plugins.cmake) + id("base") +} + +// Read the target platform passed from GitHub Actions (e.g., -Pplatform=linux_arm64) +val targetPlatform: String = (project.findProperty("platform") as? String) ?: run { + val os = OperatingSystem.current() + val arch = System.getProperty("os.arch").lowercase().trim() + + val osName = when { + os.isLinux -> "linux" + os.isMacOsX -> "macos" + os.isWindows -> "windows" + else -> error("Unsupported OS: ${os.name}") + } + + val archName = when { + arch == "amd64" || arch == "x86_64" -> { + if (os.isWindows) "x86_64" else "x86-64" + } + arch == "aarch64" || arch == "arm64" -> "arm64" + arch.startsWith("arm") -> "arm" + else -> error("Unsupported Architecture: $arch") + } + + "${osName}_${archName}" +} + +logger.lifecycle("Building webrtc-jni for platform: $targetPlatform") + +cmake { + toolchains { + when (targetPlatform) { + "linux_x86-64" -> { + register(targetPlatform) { + operatingSystem.set(OperatingSystem.LINUX) + architecture.set("x86_64") + toolchainFile.set(file("src/main/cpp/toolchain/x86_64-linux-clang.cmake")) + } + } + "linux_arm64" -> { + register(targetPlatform) { + operatingSystem.set(OperatingSystem.LINUX) + architecture.set("aarch64") + toolchainFile.set(file("src/main/cpp/toolchain/aarch64-linux-clang.cmake")) + } + } + "linux_arm" -> { + register(targetPlatform) { + operatingSystem.set(OperatingSystem.LINUX) + architecture.set("arm") + toolchainFile.set(file("src/main/cpp/toolchain/aarch32-linux-clang.cmake")) + } + } + "windows_x86_64" -> { + register(targetPlatform) { + operatingSystem.set(OperatingSystem.WINDOWS) + architecture.set("x86_64") + generator.set("Visual Studio 17 2022") + toolchainFile.set(file("src/main/cpp/toolchain/x86_64-windows-clang.cmake")) + } + } + "macos_x86-64" -> { + register(targetPlatform) { + operatingSystem.set(OperatingSystem.MAC_OS) + architecture.set("x86_64") + toolchainFile.set(file("src/main/cpp/toolchain/x86_64-macos-cross.cmake")) + } + } + "macos_arm64" -> { + register(targetPlatform) { + operatingSystem.set(OperatingSystem.MAC_OS) + architecture.set("aarch64") + toolchainFile.set(file("src/main/cpp/toolchain/aarch64-macos-clang.cmake")) + } + } + else -> { + error("Unsupported target platform: $targetPlatform") + } + } + } + + libraries { + register("webrtc-java") { + sources.from(fileTree("src/main/cpp") { + include("**/*.cpp") + include("**/*.h") + }) + + if (targetPlatform != "host") { + toolchains.add(targetPlatform) + } else { + toolchains.add("host") + } + } + } +} + +val nativeJar by tasks.registering(Jar::class) { + val toolchainPart = targetPlatform.replaceFirstChar { if (it.isLowerCase()) it.titlecase(java.util.Locale.getDefault()) else it.toString() } + + dependsOn("cmakeAssemble${toolchainPart}Release") + + archiveBaseName.set("webrtc-java") + + val classifier = targetPlatform.replace("_", "-") + archiveClassifier.set(classifier) + + from(layout.buildDirectory.dir("cmake/$targetPlatform/Release")) { + include("**/*.so", "**/*.dll", "**/*.dylib") + } + + destinationDirectory.set(layout.buildDirectory.dir("libs")) +} + +artifacts { + add("archives", nativeJar) + add("default", nativeJar) +} + +tasks.named("assemble") { + dependsOn(nativeJar) +} diff --git a/webrtc-jni/pom.xml b/webrtc-jni/pom.xml deleted file mode 100644 index 99fe25e..0000000 --- a/webrtc-jni/pom.xml +++ /dev/null @@ -1,215 +0,0 @@ - - - 4.0.0 - - - dev.onvoid.webrtc - webrtc-java-parent - 0.15.0-SNAPSHOT - - - webrtc-java-jni - pom - - - branch-heads/7339 - Release - - - - - - webrtc-java-${project.version} - - - - org.apache.maven.plugins - maven-jar-plugin - - - prepare-package - - jar - - - ${platform.classifier} - ${project.build.directory}/lib - - false - - ${platform.module} - - - - - - - - org.apache.maven.plugins - maven-install-plugin - - true - - - - install-classifier - package - - install-file - - - ${project.build.directory}/webrtc-java-${project.version}-${platform.classifier}.jar - ${platform.classifier} - ${project.groupId} - webrtc-java - ${project.version} - jar - false - - - - - - com.googlecode.cmake-maven-project - cmake-maven-plugin - 3.22.1-b1 - - - cmake-generate - generate-resources - - generate - - - false - src/main/cpp - ${project.build.directory}/${platform.classifier} - - - - - - - - - - - - - - cmake-compile - generate-resources - - compile - - - false - ${cmake.config} - install - ${project.build.directory}/${platform.classifier} - - - - - - - - - - windows-x86_64 - - - windows - amd64 - - - - -Ax64 - ${cmake.build.type} - - - - windows-clang - - - windows - amd64 - - - - -T ClangCL - toolchain/x86_64-windows-clang.cmake - - - - linux-x86_64 - - - linux - amd64 - - - - toolchain/x86_64-linux-clang.cmake - - - - linux-aarch32 - - - linux - aarch32 - - - - toolchain/aarch32-linux-clang.cmake - - - - linux-aarch64 - - - linux - aarch64 - - - - toolchain/aarch64-linux-clang.cmake - - - - macos-aarch64 - - - mac - aarch64 - - - - toolchain/aarch64-macos-clang.cmake - - - - macos-cross-x86_64 - - toolchain/x86_64-macos-cross.cmake - - - - diff --git a/webrtc/build.gradle.kts b/webrtc/build.gradle.kts new file mode 100644 index 0000000..bafdc74 --- /dev/null +++ b/webrtc/build.gradle.kts @@ -0,0 +1,78 @@ +plugins { + `java-library` + `maven-publish` + `signing` +} + +dependencies { + api(project(":webrtc-jni")) + + testImplementation(libs.bundles.junit) + testRuntimeOnly(libs.junit.platform.launcher) + testRuntimeOnly(project(":webrtc-jni")) +} + +configure { + toolchain.languageVersion.set(JavaLanguageVersion.of(17)) + withJavadocJar() + withSourcesJar() +} + +publishing { + publications { + create("maven") { + artifactId = "webrtc-java" + from(components["java"]) + + pom { + name.set("webrtc-java") + description.set("Java native interface implementation based on the free, open WebRTC project.") + url.set("https://github.com/Kas-tle/webrtc-java") + licenses { + license { + name.set("The Apache Software License, Version 2.0") + url.set("http://www.apache.org/licenses/LICENSE-2.0.txt") + } + } + developers { + developer { + name.set("Kas-tle") + organization.set("Kas-tle") + organizationUrl.set("https://github.com/Kas-tle") + } + } + scm { + connection.set("scm:git:git://github.com/Kas-tle/webrtc-java.git") + url.set("https://github.com/Kas-tle/webrtc-java") + } + } + + // These jars are downloaded by the GitHub Actions "Publish" job into a folder + val nativeLibsDir = project.findProperty("nativeLibsDir") as? String + if (nativeLibsDir != null) { + val dir = file(nativeLibsDir) + if (dir.exists()) { + dir.listFiles()?.filter { it.name.endsWith(".jar") && it.name.contains("webrtc-java") }?.forEach { jarFile -> + // Don't re-attach the main jar + if (!jarFile.name.equals("webrtc-java-${version}.jar") && !jarFile.name.contains("-sources") && !jarFile.name.contains("-javadoc")) { + artifact(jarFile) { + // Extract classifier from filename: webrtc-java-0.15.0-linux-x86_64.jar -> linux-x86_64 + val classifierStr = jarFile.name + .replace("webrtc-java-${version}-", "") + .replace(".jar", "") + classifier = classifierStr + } + } + } + } + } + } + } +} + +signing { + if (System.getenv("PGP_SECRET") != null) { + useInMemoryPgpKeys(System.getenv("PGP_SECRET"), System.getenv("PGP_PASSPHRASE")) + sign(publishing.publications["maven"]) + } +} diff --git a/webrtc/pom.xml b/webrtc/pom.xml deleted file mode 100644 index 6c84184..0000000 --- a/webrtc/pom.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - 4.0.0 - - - dev.onvoid.webrtc - webrtc-java-parent - 0.15.0-SNAPSHOT - - - webrtc-java - - webrtc-java - - - - - org.apache.maven.plugins - maven-antrun-plugin - - - attach-artifact - package - - run - - - - - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - - --add-opens webrtc.java/dev.onvoid.webrtc=ALL-UNNAMED - --add-opens webrtc.java/dev.onvoid.webrtc.logging=ALL-UNNAMED - - - - - - - - - ${project.groupId} - ${project.artifactId} - ${project.version} - ${platform.classifier} - - - \ No newline at end of file From dd9eb1aa88efce4396ccf951c0202f7858ddd4f9 Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Mon, 22 Dec 2025 02:42:27 -0800 Subject: [PATCH 37/81] Switch to execute for gradle and add wrapper Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .gitignore | 1 + build.gradle.kts | 8 +- gradle/libs.versions.toml | 5 +- gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 45633 bytes gradle/wrapper/gradle-wrapper.properties | 7 + gradlew | 248 +++++++++++++++++++++++ gradlew.bat | 93 +++++++++ webrtc-jni/build.gradle.kts | 189 ++++++++--------- webrtc/build.gradle.kts | 13 ++ 9 files changed, 459 insertions(+), 105 deletions(-) create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat diff --git a/.gitignore b/.gitignore index 83ecbfa..79bc955 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ gradle-app.setting !gradle-wrapper.jar !gradle-wrapper.properties +bin/ # Local sysroot files webrtc-jni/src/main/cpp/dependencies/webrtc/linux/debian*amd64* diff --git a/build.gradle.kts b/build.gradle.kts index ded358a..b27b6ab 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,7 @@ plugins { alias(libs.plugins.nmcp) + `maven-publish` + `eclipse` } allprojects { @@ -11,13 +13,13 @@ allprojects { } } -nmcp { - publishAggregation { +nmcpAggregation { + centralPortal { project(":webrtc") username.set(System.getenv("MAVEN_CENTRAL_USERNAME")) password.set(System.getenv("MAVEN_CENTRAL_PASSWORD")) - publicationType.set("AUTOMATIC") + publishingType.set("AUTOMATIC") } } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6ad9d08..7a27fb6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,6 +10,9 @@ junit-jupiter-api = { group = "org.junit.jupiter", name = "junit-jupiter-api", v junit-jupiter-params = { group = "org.junit.jupiter", name = "junit-jupiter-params", version.ref = "junit" } junit-platform-launcher = { group = "org.junit.platform", name = "junit-platform-launcher" } +[bundles] +junit = ["junit-jupiter-engine", "junit-jupiter-api", "junit-jupiter-params", "junit-platform-launcher"] + [plugins] -nmcp = { id = "com.gradleup.nmcp", version.ref = "nmcp" } +nmcp = { id = "com.gradleup.nmcp.aggregation", version.ref = "nmcp" } cmake = { id = "io.github.tomaki19.gradle-cmake-plugin", version.ref = "cmakePlugin" } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..f8e1ee3125fe0768e9a76ee977ac089eb657005e GIT binary patch literal 45633 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�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 literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..bad7c24 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..adff685 --- /dev/null +++ b/gradlew @@ -0,0 +1,248 @@ +#!/bin/sh + +# +# Copyright © 2015 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..e509b2d --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,93 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/webrtc-jni/build.gradle.kts b/webrtc-jni/build.gradle.kts index c2252d4..575a2e9 100644 --- a/webrtc-jni/build.gradle.kts +++ b/webrtc-jni/build.gradle.kts @@ -1,127 +1,114 @@ -import io.github.tomaki19.gradle.cmake.extension.api.CMakeToolchain import org.gradle.internal.os.OperatingSystem plugins { - alias(libs.plugins.cmake) - id("base") + `java` } -// Read the target platform passed from GitHub Actions (e.g., -Pplatform=linux_arm64) -val targetPlatform: String = (project.findProperty("platform") as? String) ?: run { - val os = OperatingSystem.current() - val arch = System.getProperty("os.arch").lowercase().trim() - - val osName = when { - os.isLinux -> "linux" - os.isMacOsX -> "macos" - os.isWindows -> "windows" - else -> error("Unsupported OS: ${os.name}") +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(17)) } +} - val archName = when { - arch == "amd64" || arch == "x86_64" -> { - if (os.isWindows) "x86_64" else "x86-64" - } - arch == "aarch64" || arch == "arm64" -> "arm64" - arch.startsWith("arm") -> "arm" - else -> error("Unsupported Architecture: $arch") - } +val currentOs = OperatingSystem.current() +val rawArch = System.getProperty("os.arch").lowercase().trim() - "${osName}_${archName}" +val osFamily = when { + currentOs.isLinux -> "linux" + currentOs.isMacOsX -> "macos" + currentOs.isWindows -> "windows" + else -> error("Unsupported OS: ${currentOs.name}") } -logger.lifecycle("Building webrtc-jni for platform: $targetPlatform") - -cmake { - toolchains { - when (targetPlatform) { - "linux_x86-64" -> { - register(targetPlatform) { - operatingSystem.set(OperatingSystem.LINUX) - architecture.set("x86_64") - toolchainFile.set(file("src/main/cpp/toolchain/x86_64-linux-clang.cmake")) - } - } - "linux_arm64" -> { - register(targetPlatform) { - operatingSystem.set(OperatingSystem.LINUX) - architecture.set("aarch64") - toolchainFile.set(file("src/main/cpp/toolchain/aarch64-linux-clang.cmake")) - } - } - "linux_arm" -> { - register(targetPlatform) { - operatingSystem.set(OperatingSystem.LINUX) - architecture.set("arm") - toolchainFile.set(file("src/main/cpp/toolchain/aarch32-linux-clang.cmake")) - } - } - "windows_x86_64" -> { - register(targetPlatform) { - operatingSystem.set(OperatingSystem.WINDOWS) - architecture.set("x86_64") - generator.set("Visual Studio 17 2022") - toolchainFile.set(file("src/main/cpp/toolchain/x86_64-windows-clang.cmake")) - } - } - "macos_x86-64" -> { - register(targetPlatform) { - operatingSystem.set(OperatingSystem.MAC_OS) - architecture.set("x86_64") - toolchainFile.set(file("src/main/cpp/toolchain/x86_64-macos-cross.cmake")) - } - } - "macos_arm64" -> { - register(targetPlatform) { - operatingSystem.set(OperatingSystem.MAC_OS) - architecture.set("aarch64") - toolchainFile.set(file("src/main/cpp/toolchain/aarch64-macos-clang.cmake")) - } - } - else -> { - error("Unsupported target platform: $targetPlatform") - } - } +val osArch = when { + rawArch == "amd64" || rawArch == "x86_64" || rawArch == "x86-64" -> "x86_64" + rawArch == "aarch64" || rawArch == "arm64" -> "aarch64" + rawArch.startsWith("arm") -> "aarch32" + else -> error("Unsupported Architecture: $rawArch") +} + +val targetPlatform = (project.findProperty("platform") as? String) ?: "$osFamily-$osArch" +val platformClassifier = targetPlatform.replace("_", "-") + +logger.lifecycle("Configuring webrtc-jni for Platform: $targetPlatform") + +val toolchainFile = file("src/main/cpp/toolchain").resolve( + when { + targetPlatform == "linux-x86_64" -> "x86_64-linux-clang.cmake" + targetPlatform == "linux-aarch64" -> "aarch64-linux-clang.cmake" + targetPlatform == "linux-aarch32" -> "aarch32-linux-clang.cmake" + targetPlatform == "windows-x86_64" -> "x86_64-windows-clang.cmake" + targetPlatform == "macos-x86_64" -> "x86_64-macos-cross.cmake" + targetPlatform == "macos-aarch64" -> "aarch64-macos-clang.cmake" + else -> "unknown-toolchain.cmake" } +) - libraries { - register("webrtc-java") { - sources.from(fileTree("src/main/cpp") { - include("**/*.cpp") - include("**/*.h") - }) - - if (targetPlatform != "host") { - toolchains.add(targetPlatform) - } else { - toolchains.add("host") - } - } +val cmakeBuildDir = layout.buildDirectory.dir("cmake/$targetPlatform") + +val configureNative by tasks.registering(Exec::class) { + group = "build" + workingDir = file("src/main/cpp") + + doFirst { + cmakeBuildDir.get().asFile.mkdirs() } -} -val nativeJar by tasks.registering(Jar::class) { - val toolchainPart = targetPlatform.replaceFirstChar { if (it.isLowerCase()) it.titlecase(java.util.Locale.getDefault()) else it.toString() } + commandLine("cmake") + args("-S", ".", "-B", cmakeBuildDir.get().asFile.absolutePath) + args("-DCMAKE_BUILD_TYPE=Release") + + if (toolchainFile.exists()) { + args("-DWEBRTC_TOOLCHAIN_FILE=${toolchainFile.absolutePath}") + } - dependsOn("cmakeAssemble${toolchainPart}Release") + args("-DOUTPUT_NAME_SUFFIX=$targetPlatform") + args("-DCMAKE_EXPORT_COMPILE_COMMANDS=1") +} - archiveBaseName.set("webrtc-java") +val buildNative by tasks.registering(Exec::class) { + group = "build" + dependsOn(configureNative) - val classifier = targetPlatform.replace("_", "-") - archiveClassifier.set(classifier) + commandLine("cmake") + args("--build", cmakeBuildDir.get().asFile.absolutePath) + args("--config", "Release") + + if (!currentOs.isWindows) { + args("-j", Runtime.getRuntime().availableProcessors()) + } +} - from(layout.buildDirectory.dir("cmake/$targetPlatform/Release")) { +val copyNativeLibs by tasks.registering(Copy::class) { + dependsOn(buildNative) + + from(fileTree(cmakeBuildDir).matching { include("**/*.so", "**/*.dll", "**/*.dylib") + exclude("**/*.lib", "**/*.exp", "**/obj/**", "**/CMakeFiles/**") + }) + + into(layout.buildDirectory.dir("resources/main")) + + rename { filename -> + if (filename.contains("webrtc-java")) { + val ext = if (filename.endsWith(".dll")) "dll" else if (filename.endsWith(".dylib")) "dylib" else "so" + val prefix = if (ext == "dll") "" else "lib" + "${prefix}webrtc-java-${targetPlatform}.${ext}" + } else { + filename + } } - destinationDirectory.set(layout.buildDirectory.dir("libs")) + eachFile { relativePath = RelativePath(true, name) } } -artifacts { - add("archives", nativeJar) - add("default", nativeJar) +tasks.named("processResources") { + dependsOn(copyNativeLibs) } -tasks.named("assemble") { - dependsOn(nativeJar) +tasks.named("jar") { + archiveBaseName.set("webrtc-java") + archiveClassifier.set(platformClassifier) } + +tasks.withType { enabled = false } \ No newline at end of file diff --git a/webrtc/build.gradle.kts b/webrtc/build.gradle.kts index bafdc74..0ad1fca 100644 --- a/webrtc/build.gradle.kts +++ b/webrtc/build.gradle.kts @@ -18,6 +18,19 @@ configure { withSourcesJar() } +tasks.named("test") { + useJUnitPlatform() + + jvmArgs( + "--add-opens=webrtc.java/dev.onvoid.webrtc=ALL-UNNAMED", + "--add-opens=webrtc.java/dev.onvoid.webrtc.logging=ALL-UNNAMED" + ) + + testLogging { + events("passed", "skipped", "failed") + } +} + publishing { publications { create("maven") { From 1cb1be23b184b29a4e250f4c7dd0d53f4eabf6b0 Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Wed, 24 Dec 2025 11:58:43 -0800 Subject: [PATCH 38/81] Remove unused imports Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- webrtc/src/main/java/dev/onvoid/webrtc/RTCPeerConnection.java | 2 -- .../src/test/java/dev/onvoid/webrtc/RTCPeerConnectionTests.java | 2 -- 2 files changed, 4 deletions(-) diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCPeerConnection.java b/webrtc/src/main/java/dev/onvoid/webrtc/RTCPeerConnection.java index d111ad4..252ad2c 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCPeerConnection.java +++ b/webrtc/src/main/java/dev/onvoid/webrtc/RTCPeerConnection.java @@ -18,8 +18,6 @@ import dev.onvoid.webrtc.internal.NativeObject; -import java.util.List; - /** * The RTCPeerConnection represents a WebRTC connection between the local * computer and a remote peer. Communications are coordinated by the exchange of diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/RTCPeerConnectionTests.java b/webrtc/src/test/java/dev/onvoid/webrtc/RTCPeerConnectionTests.java index e86e529..21eb675 100644 --- a/webrtc/src/test/java/dev/onvoid/webrtc/RTCPeerConnectionTests.java +++ b/webrtc/src/test/java/dev/onvoid/webrtc/RTCPeerConnectionTests.java @@ -18,8 +18,6 @@ import static org.junit.jupiter.api.Assertions.*; -import java.util.ArrayList; -import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicReference; From 1896d49c3e825c7f78a34099f84e8b5c345af78d Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Wed, 24 Dec 2025 13:05:50 -0800 Subject: [PATCH 39/81] Package renaming Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- README.md | 2 +- build.gradle.kts | 4 +- gradle.properties | 2 + webrtc-jni/build.gradle.kts | 6 +- webrtc-jni/src/main/cpp/include/JNI_Logging.h | 32 ++--- .../cpp/include/JNI_PeerConnectionFactory.h | 20 +-- .../src/main/cpp/include/JNI_RTCDataChannel.h | 74 +++++----- .../main/cpp/include/JNI_RTCDtlsTransport.h | 32 ++--- .../main/cpp/include/JNI_RTCPeerConnection.h | 134 +++++++++--------- .../main/cpp/include/JNI_RefCountedObject.h | 14 +- webrtc-jni/src/main/cpp/include/JNI_WebRTC.h | 6 +- webrtc-jni/src/main/cpp/src/JNI_Logging.cpp | 10 +- .../cpp/src/JNI_PeerConnectionFactory.cpp | 6 +- .../src/main/cpp/src/JNI_RTCDataChannel.cpp | 32 ++--- .../src/main/cpp/src/JNI_RTCDtlsTransport.cpp | 10 +- .../main/cpp/src/JNI_RTCPeerConnection.cpp | 50 +++---- .../src/main/cpp/src/JNI_RefCountedObject.cpp | 4 +- webrtc/build.gradle.kts | 4 +- .../CreateSessionDescriptionObserver.java | 2 +- .../webrtc/PeerConnectionFactory.java | 6 +- .../webrtc/PeerConnectionObserver.java | 2 +- .../webrtc/PortAllocatorConfig.java | 2 +- .../webrtc/RTCAnswerOptions.java | 2 +- .../webrtc/RTCBundlePolicy.java | 2 +- .../webrtc/RTCCertificatePEM.java | 2 +- .../webrtc/RTCConfiguration.java | 2 +- .../webrtc/RTCDataChannel.java | 4 +- .../webrtc/RTCDataChannelBuffer.java | 2 +- .../webrtc/RTCDataChannelInit.java | 2 +- .../webrtc/RTCDataChannelObserver.java | 2 +- .../webrtc/RTCDataChannelState.java | 2 +- .../webrtc/RTCDtlsTransport.java | 4 +- .../webrtc/RTCDtlsTransportObserver.java | 2 +- .../webrtc/RTCDtlsTransportState.java | 2 +- .../webrtc/RTCDtxStatus.java | 2 +- .../webrtc/RTCIceCandidate.java | 2 +- .../webrtc/RTCIceConnectionState.java | 2 +- .../webrtc/RTCIceGatheringState.java | 2 +- .../webrtc/RTCIceServer.java | 2 +- .../webrtc/RTCIceTransport.java | 4 +- .../webrtc/RTCIceTransportPolicy.java | 2 +- .../webrtc/RTCOfferAnswerOptions.java | 2 +- .../webrtc/RTCOfferOptions.java | 2 +- .../webrtc/RTCPeerConnection.java | 4 +- .../RTCPeerConnectionIceErrorEvent.java | 2 +- .../webrtc/RTCPeerConnectionState.java | 2 +- .../webrtc/RTCPriorityType.java | 2 +- .../webrtc/RTCRtcpMuxPolicy.java | 2 +- .../{onvoid => kastle}/webrtc/RTCSdpType.java | 2 +- .../webrtc/RTCSessionDescription.java | 2 +- .../webrtc/RTCSignalingState.java | 2 +- .../{onvoid => kastle}/webrtc/RTCStats.java | 2 +- .../webrtc/RTCStatsCollectorCallback.java | 2 +- .../webrtc/RTCStatsReport.java | 2 +- .../webrtc/RTCStatsType.java | 2 +- .../webrtc/SetSessionDescriptionObserver.java | 2 +- .../webrtc/TlsCertPolicy.java | 2 +- .../internal/DisposableNativeObject.java | 2 +- .../webrtc/internal/NativeClassLoader.java | 2 +- .../webrtc/internal/NativeLoader.java | 2 +- .../webrtc/internal/NativeObject.java | 2 +- .../webrtc/internal/RefCounted.java | 2 +- .../webrtc/internal/RefCountedObject.java | 2 +- .../webrtc/logging/LogSink.java | 2 +- .../webrtc/logging/Logging.java | 4 +- webrtc/src/main/java/module-info.java | 4 +- .../META-INF/native-image/jni-config.json | 38 ++--- .../META-INF/native-image/reflect-config.json | 48 +++---- .../webrtc/PeerConnectionFactoryTests.java | 2 +- .../PortAllocatorConfigIntegrationTest.java | 2 +- .../webrtc/PortAllocatorConfigTests.java | 2 +- .../webrtc/RTCConfigurationTests.java | 2 +- .../webrtc/RTCDataChannelTests.java | 2 +- .../webrtc/RTCPeerConnectionTests.java | 2 +- .../{onvoid => kastle}/webrtc/TestBase.java | 2 +- .../webrtc/TestCreateDescObserver.java | 2 +- .../webrtc/TestPeerConnection.java | 2 +- .../webrtc/TestSetDescObserver.java | 2 +- .../webrtc/logging/LoggingTests.java | 6 +- 80 files changed, 337 insertions(+), 331 deletions(-) create mode 100644 gradle.properties rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/CreateSessionDescriptionObserver.java (98%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/PeerConnectionFactory.java (93%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/PeerConnectionObserver.java (99%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/PortAllocatorConfig.java (99%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCAnswerOptions.java (96%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCBundlePolicy.java (98%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCCertificatePEM.java (98%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCConfiguration.java (98%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCDataChannel.java (98%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCDataChannelBuffer.java (98%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCDataChannelInit.java (98%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCDataChannelObserver.java (98%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCDataChannelState.java (97%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCDtlsTransport.java (97%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCDtlsTransportObserver.java (97%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCDtlsTransportState.java (97%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCDtxStatus.java (96%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCIceCandidate.java (98%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCIceConnectionState.java (98%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCIceGatheringState.java (97%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCIceServer.java (99%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCIceTransport.java (94%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCIceTransportPolicy.java (98%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCOfferAnswerOptions.java (98%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCOfferOptions.java (98%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCPeerConnection.java (99%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCPeerConnectionIceErrorEvent.java (99%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCPeerConnectionState.java (98%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCPriorityType.java (97%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCRtcpMuxPolicy.java (98%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCSdpType.java (98%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCSessionDescription.java (98%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCSignalingState.java (98%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCStats.java (99%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCStatsCollectorCallback.java (97%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCStatsReport.java (98%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/RTCStatsType.java (99%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/SetSessionDescriptionObserver.java (97%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/TlsCertPolicy.java (97%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/internal/DisposableNativeObject.java (96%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/internal/NativeClassLoader.java (96%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/internal/NativeLoader.java (99%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/internal/NativeObject.java (96%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/internal/RefCounted.java (97%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/internal/RefCountedObject.java (95%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/logging/LogSink.java (95%) rename webrtc/src/main/java/dev/{onvoid => kastle}/webrtc/logging/Logging.java (96%) rename webrtc/src/test/java/dev/{onvoid => kastle}/webrtc/PeerConnectionFactoryTests.java (97%) rename webrtc/src/test/java/dev/{onvoid => kastle}/webrtc/PortAllocatorConfigIntegrationTest.java (99%) rename webrtc/src/test/java/dev/{onvoid => kastle}/webrtc/PortAllocatorConfigTests.java (99%) rename webrtc/src/test/java/dev/{onvoid => kastle}/webrtc/RTCConfigurationTests.java (98%) rename webrtc/src/test/java/dev/{onvoid => kastle}/webrtc/RTCDataChannelTests.java (99%) rename webrtc/src/test/java/dev/{onvoid => kastle}/webrtc/RTCPeerConnectionTests.java (99%) rename webrtc/src/test/java/dev/{onvoid => kastle}/webrtc/TestBase.java (97%) rename webrtc/src/test/java/dev/{onvoid => kastle}/webrtc/TestCreateDescObserver.java (98%) rename webrtc/src/test/java/dev/{onvoid => kastle}/webrtc/TestPeerConnection.java (99%) rename webrtc/src/test/java/dev/{onvoid => kastle}/webrtc/TestSetDescObserver.java (98%) rename webrtc/src/test/java/dev/{onvoid => kastle}/webrtc/logging/LoggingTests.java (90%) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2ea33fe..fecbdbe 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -101,7 +101,7 @@ jobs: mvn release:prepare -DskipTests -DpushChanges=false -DdevelopmentVersion=${{ github.event.inputs.developmentVersion }} # Get the release version from the release.properties file - RELEASE_VERSION=$(grep "project.rel.dev.onvoid.webrtc\\\:webrtc-java=" release.properties | cut -d'=' -f2) + RELEASE_VERSION=$(grep "project.rel.dev.kastle.webrtc\\\:webrtc-java=" release.properties | cut -d'=' -f2) echo "Extracted release version from release.properties: $RELEASE_VERSION" # Update versions.ts file diff --git a/README.md b/README.md index 6a93e40..1dc97a3 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ [![Build Status](https://img.shields.io/github/actions/workflow/status/devopvoid/webrtc-java/build.yml?label=Build&logo=github)](https://github.com/devopvoid/webrtc-java/actions) -[![Maven Central](https://img.shields.io/maven-central/v/dev.onvoid.webrtc/webrtc-java?label=Maven%20Central&logo=apache-maven)](https://search.maven.org/artifact/dev.onvoid.webrtc/webrtc-java) +[![Maven Central](https://img.shields.io/maven-central/v/dev.kastle.webrtc/webrtc-java?label=Maven%20Central&logo=apache-maven)](https://search.maven.org/artifact/dev.kastle.webrtc/webrtc-java)

    webrtc-java diff --git a/build.gradle.kts b/build.gradle.kts index b27b6ab..56499ef 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,8 +5,8 @@ plugins { } allprojects { - group = "dev.onvoid.webrtc" - version = "0.15.0-SNAPSHOT" + group = "dev.kastle.webrtc" + version = rootProject.property("version") as String repositories { mavenCentral() diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..b70178f --- /dev/null +++ b/gradle.properties @@ -0,0 +1,2 @@ +webrtc.branch=branch-heads/7339 +version=1.0.0 \ No newline at end of file diff --git a/webrtc-jni/build.gradle.kts b/webrtc-jni/build.gradle.kts index 575a2e9..61efc21 100644 --- a/webrtc-jni/build.gradle.kts +++ b/webrtc-jni/build.gradle.kts @@ -27,7 +27,7 @@ val osArch = when { else -> error("Unsupported Architecture: $rawArch") } -val targetPlatform = (project.findProperty("platform") as? String) ?: "$osFamily-$osArch" +val targetPlatform = (System.getenv("WEBRTC_PLATFORM") as? String) ?: "$osFamily-$osArch" val platformClassifier = targetPlatform.replace("_", "-") logger.lifecycle("Configuring webrtc-jni for Platform: $targetPlatform") @@ -62,6 +62,10 @@ val configureNative by tasks.registering(Exec::class) { args("-DWEBRTC_TOOLCHAIN_FILE=${toolchainFile.absolutePath}") } + val webrtcBranch = rootProject.property("webrtc.branch") as String? ?: "master" + logger.lifecycle("Using WebRTC Branch: $webrtcBranch") + + args("-DWEBRTC_BRANCH=$webrtcBranch") args("-DOUTPUT_NAME_SUFFIX=$targetPlatform") args("-DCMAKE_EXPORT_COMPILE_COMMANDS=1") } diff --git a/webrtc-jni/src/main/cpp/include/JNI_Logging.h b/webrtc-jni/src/main/cpp/include/JNI_Logging.h index 2360e11..4f7fff4 100644 --- a/webrtc-jni/src/main/cpp/include/JNI_Logging.h +++ b/webrtc-jni/src/main/cpp/include/JNI_Logging.h @@ -1,50 +1,50 @@ /* DO NOT EDIT THIS FILE - it is machine generated */ #include -/* Header for class dev_onvoid_webrtc_logging_Logging */ +/* Header for class dev_kastle_webrtc_logging_Logging */ -#ifndef _Included_dev_onvoid_webrtc_logging_Logging -#define _Included_dev_onvoid_webrtc_logging_Logging +#ifndef _Included_dev_kastle_webrtc_logging_Logging +#define _Included_dev_kastle_webrtc_logging_Logging #ifdef __cplusplus extern "C" { #endif /* - * Class: dev_onvoid_webrtc_logging_Logging + * Class: dev_kastle_webrtc_logging_Logging * Method: addLogSink - * Signature: (Ldev/onvoid/webrtc/logging/Logging/Severity;Ldev/onvoid/webrtc/logging/LogSink;)V + * Signature: (Ldev/kastle/webrtc/logging/Logging/Severity;Ldev/kastle/webrtc/logging/LogSink;)V */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_logging_Logging_addLogSink + JNIEXPORT void JNICALL Java_dev_kastle_webrtc_logging_Logging_addLogSink (JNIEnv *, jclass, jobject, jobject); /* - * Class: dev_onvoid_webrtc_logging_Logging + * Class: dev_kastle_webrtc_logging_Logging * Method: log - * Signature: (Ldev/onvoid/webrtc/logging/Logging/Severity;Ljava/lang/String;)V + * Signature: (Ldev/kastle/webrtc/logging/Logging/Severity;Ljava/lang/String;)V */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_logging_Logging_log + JNIEXPORT void JNICALL Java_dev_kastle_webrtc_logging_Logging_log (JNIEnv *, jclass, jobject, jstring); /* - * Class: dev_onvoid_webrtc_logging_Logging + * Class: dev_kastle_webrtc_logging_Logging * Method: logToDebug - * Signature: (Ldev/onvoid/webrtc/logging/Logging/Severity;)V + * Signature: (Ldev/kastle/webrtc/logging/Logging/Severity;)V */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_logging_Logging_logToDebug + JNIEXPORT void JNICALL Java_dev_kastle_webrtc_logging_Logging_logToDebug (JNIEnv *, jclass, jobject); /* - * Class: dev_onvoid_webrtc_logging_Logging + * Class: dev_kastle_webrtc_logging_Logging * Method: logThreads * Signature: (Z)V */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_logging_Logging_logThreads + JNIEXPORT void JNICALL Java_dev_kastle_webrtc_logging_Logging_logThreads (JNIEnv *, jclass, jboolean); /* - * Class: dev_onvoid_webrtc_logging_Logging + * Class: dev_kastle_webrtc_logging_Logging * Method: logTimestamps * Signature: (Z)V */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_logging_Logging_logTimestamps + JNIEXPORT void JNICALL Java_dev_kastle_webrtc_logging_Logging_logTimestamps (JNIEnv *, jclass, jboolean); #ifdef __cplusplus diff --git a/webrtc-jni/src/main/cpp/include/JNI_PeerConnectionFactory.h b/webrtc-jni/src/main/cpp/include/JNI_PeerConnectionFactory.h index 487ae19..5cf2160 100644 --- a/webrtc-jni/src/main/cpp/include/JNI_PeerConnectionFactory.h +++ b/webrtc-jni/src/main/cpp/include/JNI_PeerConnectionFactory.h @@ -1,35 +1,35 @@ /* DO NOT EDIT THIS FILE - it is machine generated */ #include -/* Header for class dev_onvoid_webrtc_PeerConnectionFactory */ +/* Header for class dev_kastle_webrtc_PeerConnectionFactory */ -#ifndef _Included_dev_onvoid_webrtc_PeerConnectionFactory -#define _Included_dev_onvoid_webrtc_PeerConnectionFactory +#ifndef _Included_dev_kastle_webrtc_PeerConnectionFactory +#define _Included_dev_kastle_webrtc_PeerConnectionFactory #ifdef __cplusplus extern "C" { #endif /* - * Class: dev_onvoid_webrtc_PeerConnectionFactory + * Class: dev_kastle_webrtc_PeerConnectionFactory * Method: createPeerConnection - * Signature: (Ldev/onvoid/webrtc/RTCConfiguration;Ldev/onvoid/webrtc/PeerConnectionObserver;)Ldev/onvoid/webrtc/RTCPeerConnection; + * Signature: (Ldev/kastle/webrtc/RTCConfiguration;Ldev/kastle/webrtc/PeerConnectionObserver;)Ldev/kastle/webrtc/RTCPeerConnection; */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_createPeerConnection + JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_PeerConnectionFactory_createPeerConnection (JNIEnv *, jobject, jobject, jobject); /* - * Class: dev_onvoid_webrtc_PeerConnectionFactory + * Class: dev_kastle_webrtc_PeerConnectionFactory * Method: dispose * Signature: ()V */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_dispose + JNIEXPORT void JNICALL Java_dev_kastle_webrtc_PeerConnectionFactory_dispose (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_PeerConnectionFactory + * Class: dev_kastle_webrtc_PeerConnectionFactory * Method: initialize * Signature: ()V */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_initialize + JNIEXPORT void JNICALL Java_dev_kastle_webrtc_PeerConnectionFactory_initialize (JNIEnv *, jobject); #ifdef __cplusplus diff --git a/webrtc-jni/src/main/cpp/include/JNI_RTCDataChannel.h b/webrtc-jni/src/main/cpp/include/JNI_RTCDataChannel.h index 12305ec..065f3c3 100644 --- a/webrtc-jni/src/main/cpp/include/JNI_RTCDataChannel.h +++ b/webrtc-jni/src/main/cpp/include/JNI_RTCDataChannel.h @@ -1,138 +1,138 @@ /* DO NOT EDIT THIS FILE - it is machine generated */ #include -/* Header for class dev_onvoid_webrtc_RTCDataChannel */ +/* Header for class dev_kastle_webrtc_RTCDataChannel */ -#ifndef _Included_dev_onvoid_webrtc_RTCDataChannel -#define _Included_dev_onvoid_webrtc_RTCDataChannel +#ifndef _Included_dev_kastle_webrtc_RTCDataChannel +#define _Included_dev_kastle_webrtc_RTCDataChannel #ifdef __cplusplus extern "C" { #endif /* - * Class: dev_onvoid_webrtc_RTCDataChannel + * Class: dev_kastle_webrtc_RTCDataChannel * Method: registerObserver - * Signature: (Ldev/onvoid/webrtc/RTCDataChannelObserver;)V + * Signature: (Ldev/kastle/webrtc/RTCDataChannelObserver;)V */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_registerObserver + JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCDataChannel_registerObserver (JNIEnv *, jobject, jobject); /* - * Class: dev_onvoid_webrtc_RTCDataChannel + * Class: dev_kastle_webrtc_RTCDataChannel * Method: unregisterObserver * Signature: ()V */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_unregisterObserver + JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCDataChannel_unregisterObserver (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCDataChannel + * Class: dev_kastle_webrtc_RTCDataChannel * Method: getLabel * Signature: ()Ljava/lang/String; */ - JNIEXPORT jstring JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getLabel + JNIEXPORT jstring JNICALL Java_dev_kastle_webrtc_RTCDataChannel_getLabel (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCDataChannel + * Class: dev_kastle_webrtc_RTCDataChannel * Method: isReliable * Signature: ()Z */ - JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_isReliable + JNIEXPORT jboolean JNICALL Java_dev_kastle_webrtc_RTCDataChannel_isReliable (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCDataChannel + * Class: dev_kastle_webrtc_RTCDataChannel * Method: isOrdered * Signature: ()Z */ - JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_isOrdered + JNIEXPORT jboolean JNICALL Java_dev_kastle_webrtc_RTCDataChannel_isOrdered (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCDataChannel + * Class: dev_kastle_webrtc_RTCDataChannel * Method: getMaxPacketLifeTime * Signature: ()I */ - JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getMaxPacketLifeTime + JNIEXPORT jint JNICALL Java_dev_kastle_webrtc_RTCDataChannel_getMaxPacketLifeTime (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCDataChannel + * Class: dev_kastle_webrtc_RTCDataChannel * Method: getMaxRetransmits * Signature: ()I */ - JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getMaxRetransmits + JNIEXPORT jint JNICALL Java_dev_kastle_webrtc_RTCDataChannel_getMaxRetransmits (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCDataChannel + * Class: dev_kastle_webrtc_RTCDataChannel * Method: getProtocol * Signature: ()Ljava/lang/String; */ - JNIEXPORT jstring JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getProtocol + JNIEXPORT jstring JNICALL Java_dev_kastle_webrtc_RTCDataChannel_getProtocol (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCDataChannel + * Class: dev_kastle_webrtc_RTCDataChannel * Method: isNegotiated * Signature: ()Z */ - JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_isNegotiated + JNIEXPORT jboolean JNICALL Java_dev_kastle_webrtc_RTCDataChannel_isNegotiated (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCDataChannel + * Class: dev_kastle_webrtc_RTCDataChannel * Method: getId * Signature: ()I */ - JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getId + JNIEXPORT jint JNICALL Java_dev_kastle_webrtc_RTCDataChannel_getId (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCDataChannel + * Class: dev_kastle_webrtc_RTCDataChannel * Method: getState - * Signature: ()Ldev/onvoid/webrtc/RTCDataChannelState; + * Signature: ()Ldev/kastle/webrtc/RTCDataChannelState; */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getState + JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCDataChannel_getState (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCDataChannel + * Class: dev_kastle_webrtc_RTCDataChannel * Method: getBufferedAmount * Signature: ()J */ - JNIEXPORT jlong JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getBufferedAmount + JNIEXPORT jlong JNICALL Java_dev_kastle_webrtc_RTCDataChannel_getBufferedAmount (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCDataChannel + * Class: dev_kastle_webrtc_RTCDataChannel * Method: close * Signature: ()V */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_close + JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCDataChannel_close (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCDataChannel + * Class: dev_kastle_webrtc_RTCDataChannel * Method: dispose * Signature: ()V */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_dispose + JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCDataChannel_dispose (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCDataChannel + * Class: dev_kastle_webrtc_RTCDataChannel * Method: sendDirectBuffer * Signature: (Ljava/nio/ByteBuffer;Z)V */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_sendDirectBuffer + JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCDataChannel_sendDirectBuffer (JNIEnv *, jobject, jobject, jboolean); /* - * Class: dev_onvoid_webrtc_RTCDataChannel + * Class: dev_kastle_webrtc_RTCDataChannel * Method: sendByteArrayBuffer * Signature: ([BZ)V */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_sendByteArrayBuffer + JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCDataChannel_sendByteArrayBuffer (JNIEnv *, jobject, jbyteArray, jboolean); #ifdef __cplusplus diff --git a/webrtc-jni/src/main/cpp/include/JNI_RTCDtlsTransport.h b/webrtc-jni/src/main/cpp/include/JNI_RTCDtlsTransport.h index 86cbf7c..92a25db 100644 --- a/webrtc-jni/src/main/cpp/include/JNI_RTCDtlsTransport.h +++ b/webrtc-jni/src/main/cpp/include/JNI_RTCDtlsTransport.h @@ -1,50 +1,50 @@ /* DO NOT EDIT THIS FILE - it is machine generated */ #include -/* Header for class dev_onvoid_webrtc_RTCDtlsTransport */ +/* Header for class dev_kastle_webrtc_RTCDtlsTransport */ -#ifndef _Included_dev_onvoid_webrtc_RTCDtlsTransport -#define _Included_dev_onvoid_webrtc_RTCDtlsTransport +#ifndef _Included_dev_kastle_webrtc_RTCDtlsTransport +#define _Included_dev_kastle_webrtc_RTCDtlsTransport #ifdef __cplusplus extern "C" { #endif /* - * Class: dev_onvoid_webrtc_RTCDtlsTransport + * Class: dev_kastle_webrtc_RTCDtlsTransport * Method: getIceTransport - * Signature: ()Ldev/onvoid/webrtc/RTCIceTransport; + * Signature: ()Ldev/kastle/webrtc/RTCIceTransport; */ -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCDtlsTransport_getIceTransport +JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCDtlsTransport_getIceTransport (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCDtlsTransport + * Class: dev_kastle_webrtc_RTCDtlsTransport * Method: getState - * Signature: ()Ldev/onvoid/webrtc/RTCDtlsTransportState; + * Signature: ()Ldev/kastle/webrtc/RTCDtlsTransportState; */ -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCDtlsTransport_getState +JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCDtlsTransport_getState (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCDtlsTransport + * Class: dev_kastle_webrtc_RTCDtlsTransport * Method: getRemoteCertificates * Signature: ()Ljava/util/List; */ -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCDtlsTransport_getRemoteCertificates +JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCDtlsTransport_getRemoteCertificates (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCDtlsTransport + * Class: dev_kastle_webrtc_RTCDtlsTransport * Method: registerObserver - * Signature: (Ldev/onvoid/webrtc/RTCDtlsTransportObserver;)V + * Signature: (Ldev/kastle/webrtc/RTCDtlsTransportObserver;)V */ -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDtlsTransport_registerObserver +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCDtlsTransport_registerObserver (JNIEnv *, jobject, jobject); /* - * Class: dev_onvoid_webrtc_RTCDtlsTransport + * Class: dev_kastle_webrtc_RTCDtlsTransport * Method: unregisterObserver * Signature: ()V */ -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDtlsTransport_unregisterObserver +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCDtlsTransport_unregisterObserver (JNIEnv *, jobject); #ifdef __cplusplus diff --git a/webrtc-jni/src/main/cpp/include/JNI_RTCPeerConnection.h b/webrtc-jni/src/main/cpp/include/JNI_RTCPeerConnection.h index 5b7fdec..4c51084 100644 --- a/webrtc-jni/src/main/cpp/include/JNI_RTCPeerConnection.h +++ b/webrtc-jni/src/main/cpp/include/JNI_RTCPeerConnection.h @@ -1,187 +1,187 @@ /* DO NOT EDIT THIS FILE - it is machine generated */ #include -/* Header for class dev_onvoid_webrtc_RTCPeerConnection */ +/* Header for class dev_kastle_webrtc_RTCPeerConnection */ -#ifndef _Included_dev_onvoid_webrtc_RTCPeerConnection -#define _Included_dev_onvoid_webrtc_RTCPeerConnection +#ifndef _Included_dev_kastle_webrtc_RTCPeerConnection +#define _Included_dev_kastle_webrtc_RTCPeerConnection #ifdef __cplusplus extern "C" { #endif /* - * Class: dev_onvoid_webrtc_RTCPeerConnection + * Class: dev_kastle_webrtc_RTCPeerConnection * Method: createDataChannel - * Signature: (Ljava/lang/String;Ldev/onvoid/webrtc/RTCDataChannelInit;)Ldev/onvoid/webrtc/RTCDataChannel; + * Signature: (Ljava/lang/String;Ldev/kastle/webrtc/RTCDataChannelInit;)Ldev/kastle/webrtc/RTCDataChannel; */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_createDataChannel + JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_createDataChannel (JNIEnv *, jobject, jstring, jobject); /* - * Class: dev_onvoid_webrtc_RTCPeerConnection + * Class: dev_kastle_webrtc_RTCPeerConnection * Method: createOffer - * Signature: (Ldev/onvoid/webrtc/RTCOfferOptions;Ldev/onvoid/webrtc/CreateSessionDescriptionObserver;)V + * Signature: (Ldev/kastle/webrtc/RTCOfferOptions;Ldev/kastle/webrtc/CreateSessionDescriptionObserver;)V */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_createOffer + JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_createOffer (JNIEnv *, jobject, jobject, jobject); /* - * Class: dev_onvoid_webrtc_RTCPeerConnection + * Class: dev_kastle_webrtc_RTCPeerConnection * Method: createAnswer - * Signature: (Ldev/onvoid/webrtc/RTCAnswerOptions;Ldev/onvoid/webrtc/CreateSessionDescriptionObserver;)V + * Signature: (Ldev/kastle/webrtc/RTCAnswerOptions;Ldev/kastle/webrtc/CreateSessionDescriptionObserver;)V */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_createAnswer + JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_createAnswer (JNIEnv *, jobject, jobject, jobject); /* - * Class: dev_onvoid_webrtc_RTCPeerConnection + * Class: dev_kastle_webrtc_RTCPeerConnection * Method: getCurrentLocalDescription - * Signature: ()Ldev/onvoid/webrtc/RTCSessionDescription; + * Signature: ()Ldev/kastle/webrtc/RTCSessionDescription; */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getCurrentLocalDescription + JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getCurrentLocalDescription (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCPeerConnection + * Class: dev_kastle_webrtc_RTCPeerConnection * Method: getLocalDescription - * Signature: ()Ldev/onvoid/webrtc/RTCSessionDescription; + * Signature: ()Ldev/kastle/webrtc/RTCSessionDescription; */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getLocalDescription + JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getLocalDescription (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCPeerConnection + * Class: dev_kastle_webrtc_RTCPeerConnection * Method: getPendingLocalDescription - * Signature: ()Ldev/onvoid/webrtc/RTCSessionDescription; + * Signature: ()Ldev/kastle/webrtc/RTCSessionDescription; */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getPendingLocalDescription + JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getPendingLocalDescription (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCPeerConnection + * Class: dev_kastle_webrtc_RTCPeerConnection * Method: getCurrentRemoteDescription - * Signature: ()Ldev/onvoid/webrtc/RTCSessionDescription; + * Signature: ()Ldev/kastle/webrtc/RTCSessionDescription; */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getCurrentRemoteDescription + JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getCurrentRemoteDescription (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCPeerConnection + * Class: dev_kastle_webrtc_RTCPeerConnection * Method: getRemoteDescription - * Signature: ()Ldev/onvoid/webrtc/RTCSessionDescription; + * Signature: ()Ldev/kastle/webrtc/RTCSessionDescription; */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getRemoteDescription + JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getRemoteDescription (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCPeerConnection + * Class: dev_kastle_webrtc_RTCPeerConnection * Method: getPendingRemoteDescription - * Signature: ()Ldev/onvoid/webrtc/RTCSessionDescription; + * Signature: ()Ldev/kastle/webrtc/RTCSessionDescription; */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getPendingRemoteDescription + JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getPendingRemoteDescription (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCPeerConnection + * Class: dev_kastle_webrtc_RTCPeerConnection * Method: setLocalDescription - * Signature: (Ldev/onvoid/webrtc/RTCSessionDescription;Ldev/onvoid/webrtc/SetSessionDescriptionObserver;)V + * Signature: (Ldev/kastle/webrtc/RTCSessionDescription;Ldev/kastle/webrtc/SetSessionDescriptionObserver;)V */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_setLocalDescription + JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_setLocalDescription (JNIEnv *, jobject, jobject, jobject); /* - * Class: dev_onvoid_webrtc_RTCPeerConnection + * Class: dev_kastle_webrtc_RTCPeerConnection * Method: setRemoteDescription - * Signature: (Ldev/onvoid/webrtc/RTCSessionDescription;Ldev/onvoid/webrtc/SetSessionDescriptionObserver;)V + * Signature: (Ldev/kastle/webrtc/RTCSessionDescription;Ldev/kastle/webrtc/SetSessionDescriptionObserver;)V */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_setRemoteDescription + JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_setRemoteDescription (JNIEnv *, jobject, jobject, jobject); /* - * Class: dev_onvoid_webrtc_RTCPeerConnection + * Class: dev_kastle_webrtc_RTCPeerConnection * Method: addIceCandidate - * Signature: (Ldev/onvoid/webrtc/RTCIceCandidate;)V + * Signature: (Ldev/kastle/webrtc/RTCIceCandidate;)V */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_addIceCandidate + JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_addIceCandidate (JNIEnv *, jobject, jobject); /* - * Class: dev_onvoid_webrtc_RTCPeerConnection + * Class: dev_kastle_webrtc_RTCPeerConnection * Method: removeIceCandidates - * Signature: ([Ldev/onvoid/webrtc/RTCIceCandidate;)V + * Signature: ([Ldev/kastle/webrtc/RTCIceCandidate;)V */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_removeIceCandidates + JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_removeIceCandidates (JNIEnv *, jobject, jobject); /* - * Class: dev_onvoid_webrtc_RTCPeerConnection + * Class: dev_kastle_webrtc_RTCPeerConnection * Method: getSignalingState - * Signature: ()Ldev/onvoid/webrtc/RTCSignalingState; + * Signature: ()Ldev/kastle/webrtc/RTCSignalingState; */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getSignalingState + JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getSignalingState (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCPeerConnection + * Class: dev_kastle_webrtc_RTCPeerConnection * Method: getIceGatheringState - * Signature: ()Ldev/onvoid/webrtc/RTCIceGatheringState; + * Signature: ()Ldev/kastle/webrtc/RTCIceGatheringState; */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getIceGatheringState + JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getIceGatheringState (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCPeerConnection + * Class: dev_kastle_webrtc_RTCPeerConnection * Method: getIceConnectionState - * Signature: ()Ldev/onvoid/webrtc/RTCIceConnectionState; + * Signature: ()Ldev/kastle/webrtc/RTCIceConnectionState; */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getIceConnectionState + JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getIceConnectionState (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCPeerConnection + * Class: dev_kastle_webrtc_RTCPeerConnection * Method: getConnectionState - * Signature: ()Ldev/onvoid/webrtc/RTCPeerConnectionState; + * Signature: ()Ldev/kastle/webrtc/RTCPeerConnectionState; */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getConnectionState + JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getConnectionState (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCPeerConnection + * Class: dev_kastle_webrtc_RTCPeerConnection * Method: getConfiguration - * Signature: ()Ldev/onvoid/webrtc/RTCConfiguration; + * Signature: ()Ldev/kastle/webrtc/RTCConfiguration; */ - JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getConfiguration + JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getConfiguration (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCPeerConnection + * Class: dev_kastle_webrtc_RTCPeerConnection * Method: setConfiguration - * Signature: (Ldev/onvoid/webrtc/RTCConfiguration;)V + * Signature: (Ldev/kastle/webrtc/RTCConfiguration;)V */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_setConfiguration + JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_setConfiguration (JNIEnv *, jobject, jobject); /* - * Class: dev_onvoid_webrtc_RTCPeerConnection + * Class: dev_kastle_webrtc_RTCPeerConnection * Method: getStats - * Signature: (Ldev/onvoid/webrtc/RTCStatsCollectorCallback;)V + * Signature: (Ldev/kastle/webrtc/RTCStatsCollectorCallback;)V */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getStats__Ldev_onvoid_webrtc_RTCStatsCollectorCallback_2 + JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getStats__Ldev_kastle_webrtc_RTCStatsCollectorCallback_2 (JNIEnv *, jobject, jobject); /* - * Class: dev_onvoid_webrtc_RTCPeerConnection + * Class: dev_kastle_webrtc_RTCPeerConnection * Method: restartIce * Signature: ()V */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_restartIce + JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_restartIce (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_RTCPeerConnection + * Class: dev_kastle_webrtc_RTCPeerConnection * Method: close * Signature: ()V */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_close + JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_close (JNIEnv *, jobject); #ifdef __cplusplus diff --git a/webrtc-jni/src/main/cpp/include/JNI_RefCountedObject.h b/webrtc-jni/src/main/cpp/include/JNI_RefCountedObject.h index 1c2ec1c..8577601 100644 --- a/webrtc-jni/src/main/cpp/include/JNI_RefCountedObject.h +++ b/webrtc-jni/src/main/cpp/include/JNI_RefCountedObject.h @@ -1,26 +1,26 @@ /* DO NOT EDIT THIS FILE - it is machine generated */ #include -/* Header for class dev_onvoid_webrtc_internal_RefCountedObject */ +/* Header for class dev_kastle_webrtc_internal_RefCountedObject */ -#ifndef _Included_dev_onvoid_webrtc_internal_RefCountedObject -#define _Included_dev_onvoid_webrtc_internal_RefCountedObject +#ifndef _Included_dev_kastle_webrtc_internal_RefCountedObject +#define _Included_dev_kastle_webrtc_internal_RefCountedObject #ifdef __cplusplus extern "C" { #endif /* - * Class: dev_onvoid_webrtc_internal_RefCountedObject + * Class: dev_kastle_webrtc_internal_RefCountedObject * Method: retain * Signature: ()V */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_internal_RefCountedObject_retain + JNIEXPORT void JNICALL Java_dev_kastle_webrtc_internal_RefCountedObject_retain (JNIEnv *, jobject); /* - * Class: dev_onvoid_webrtc_internal_RefCountedObject + * Class: dev_kastle_webrtc_internal_RefCountedObject * Method: release * Signature: ()V */ - JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_internal_RefCountedObject_release + JNIEXPORT void JNICALL Java_dev_kastle_webrtc_internal_RefCountedObject_release (JNIEnv *, jobject); #ifdef __cplusplus diff --git a/webrtc-jni/src/main/cpp/include/JNI_WebRTC.h b/webrtc-jni/src/main/cpp/include/JNI_WebRTC.h index 26405d1..e9c41a8 100644 --- a/webrtc-jni/src/main/cpp/include/JNI_WebRTC.h +++ b/webrtc-jni/src/main/cpp/include/JNI_WebRTC.h @@ -17,9 +17,9 @@ #ifndef JNI_WEBRTC_H_ #define JNI_WEBRTC_H_ -#define PKG "dev/onvoid/webrtc/" -#define PKG_INTERNAL "dev/onvoid/webrtc/internal/" -#define PKG_LOG "dev/onvoid/webrtc/logging/" +#define PKG "dev/kastle/webrtc/" +#define PKG_INTERNAL "dev/kastle/webrtc/internal/" +#define PKG_LOG "dev/kastle/webrtc/logging/" #define BOOLEAN_SIG "Ljava/lang/Boolean;" #define DOUBLE_SIG "Ljava/lang/Double;" diff --git a/webrtc-jni/src/main/cpp/src/JNI_Logging.cpp b/webrtc-jni/src/main/cpp/src/JNI_Logging.cpp index 6e680aa..c6a9ce6 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_Logging.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_Logging.cpp @@ -25,7 +25,7 @@ #include -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_logging_Logging_addLogSink +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_logging_Logging_addLogSink (JNIEnv * env, jclass caller, jobject jseverity, jobject jsink) { try { @@ -38,7 +38,7 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_logging_Logging_addLogSink } } -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_logging_Logging_log +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_logging_Logging_log (JNIEnv * env, jclass caller, jobject jseverity, jstring jmessage) { std::string message = jni::JavaString::toNative(env, jni::JavaLocalRef(env, jmessage)); @@ -48,7 +48,7 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_logging_Logging_log RTC_LOG_V(severity) << message; } -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_logging_Logging_logToDebug +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_logging_Logging_logToDebug (JNIEnv * env, jclass caller, jobject jseverity) { int rtcSeverity = jni::JavaEnums::toNative(env, jseverity); @@ -58,13 +58,13 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_logging_Logging_logToDebug } } -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_logging_Logging_logThreads +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_logging_Logging_logThreads (JNIEnv * env, jclass caller, jboolean enable) { webrtc::LogMessage::LogThreads(static_cast(enable)); } -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_logging_Logging_logTimestamps +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_logging_Logging_logTimestamps (JNIEnv * env, jclass caller, jboolean enable) { webrtc::LogMessage::LogTimestamps(static_cast(enable)); diff --git a/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp b/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp index 823a111..211f34a 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp @@ -25,7 +25,7 @@ #include "api/create_peerconnection_factory.h" -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_initialize +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_PeerConnectionFactory_initialize (JNIEnv * env, jobject caller) { try { @@ -68,7 +68,7 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_initialize } } -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_dispose +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_PeerConnectionFactory_dispose (JNIEnv * env, jobject caller) { webrtc::PeerConnectionFactoryInterface * factory = GetHandle(env, caller); @@ -107,7 +107,7 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_dispose } } -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_PeerConnectionFactory_createPeerConnection +JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_PeerConnectionFactory_createPeerConnection (JNIEnv * env, jobject caller, jobject jConfig, jobject jobserver) { if (jConfig == nullptr) { diff --git a/webrtc-jni/src/main/cpp/src/JNI_RTCDataChannel.cpp b/webrtc-jni/src/main/cpp/src/JNI_RTCDataChannel.cpp index 2bcc8b0..91fce0c 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_RTCDataChannel.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_RTCDataChannel.cpp @@ -26,7 +26,7 @@ #include -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_registerObserver +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCDataChannel_registerObserver (JNIEnv * env, jobject caller, jobject jObserver) { webrtc::DataChannelInterface * channel = GetHandle(env, caller); @@ -35,7 +35,7 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_registerObserver channel->RegisterObserver(new jni::RTCDataChannelObserver(env, jni::JavaGlobalRef(env, jObserver))); } -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_unregisterObserver +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCDataChannel_unregisterObserver (JNIEnv * env, jobject caller) { webrtc::DataChannelInterface * channel = GetHandle(env, caller); @@ -44,7 +44,7 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_unregisterObserver channel->UnregisterObserver(); } -JNIEXPORT jstring JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getLabel +JNIEXPORT jstring JNICALL Java_dev_kastle_webrtc_RTCDataChannel_getLabel (JNIEnv * env, jobject caller) { webrtc::DataChannelInterface * channel = GetHandle(env, caller); @@ -53,7 +53,7 @@ JNIEXPORT jstring JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getLabel return jni::JavaString::toJava(env, channel->label()).release(); } -JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_isReliable +JNIEXPORT jboolean JNICALL Java_dev_kastle_webrtc_RTCDataChannel_isReliable (JNIEnv * env, jobject caller) { webrtc::DataChannelInterface * channel = GetHandle(env, caller); @@ -62,7 +62,7 @@ JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_isReliable return static_cast(channel->reliable()); } -JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_isOrdered +JNIEXPORT jboolean JNICALL Java_dev_kastle_webrtc_RTCDataChannel_isOrdered (JNIEnv * env, jobject caller) { webrtc::DataChannelInterface * channel = GetHandle(env, caller); @@ -71,7 +71,7 @@ JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_isOrdered return static_cast(channel->ordered()); } -JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getMaxPacketLifeTime +JNIEXPORT jint JNICALL Java_dev_kastle_webrtc_RTCDataChannel_getMaxPacketLifeTime (JNIEnv * env, jobject caller) { webrtc::DataChannelInterface * channel = GetHandle(env, caller); @@ -80,7 +80,7 @@ JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getMaxPacketLifeTim return static_cast(channel->maxPacketLifeTime().value_or(0)); } -JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getMaxRetransmits +JNIEXPORT jint JNICALL Java_dev_kastle_webrtc_RTCDataChannel_getMaxRetransmits (JNIEnv * env, jobject caller) { webrtc::DataChannelInterface * channel = GetHandle(env, caller); @@ -89,7 +89,7 @@ JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getMaxRetransmits return static_cast(channel->maxRetransmitsOpt().value_or(0)); } -JNIEXPORT jstring JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getProtocol +JNIEXPORT jstring JNICALL Java_dev_kastle_webrtc_RTCDataChannel_getProtocol (JNIEnv * env, jobject caller) { webrtc::DataChannelInterface * channel = GetHandle(env, caller); @@ -98,7 +98,7 @@ JNIEXPORT jstring JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getProtocol return jni::JavaString::toJava(env, channel->protocol()).release(); } -JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_isNegotiated +JNIEXPORT jboolean JNICALL Java_dev_kastle_webrtc_RTCDataChannel_isNegotiated (JNIEnv * env, jobject caller) { webrtc::DataChannelInterface * channel = GetHandle(env, caller); @@ -107,7 +107,7 @@ JNIEXPORT jboolean JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_isNegotiated return static_cast(channel->negotiated()); } -JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getId +JNIEXPORT jint JNICALL Java_dev_kastle_webrtc_RTCDataChannel_getId (JNIEnv * env, jobject caller) { webrtc::DataChannelInterface * channel = GetHandle(env, caller); @@ -116,7 +116,7 @@ JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getId return static_cast(channel->id()); } -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getState +JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCDataChannel_getState (JNIEnv * env, jobject caller) { webrtc::DataChannelInterface * channel = GetHandle(env, caller); @@ -125,7 +125,7 @@ JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getState return jni::JavaEnums::toJava(env, channel->state()).release(); } -JNIEXPORT jlong JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getBufferedAmount +JNIEXPORT jlong JNICALL Java_dev_kastle_webrtc_RTCDataChannel_getBufferedAmount (JNIEnv * env, jobject caller) { webrtc::DataChannelInterface * channel = GetHandle(env, caller); @@ -134,7 +134,7 @@ JNIEXPORT jlong JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_getBufferedAmount return static_cast(channel->buffered_amount()); } -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_close +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCDataChannel_close (JNIEnv * env, jobject caller) { webrtc::DataChannelInterface * channel = GetHandle(env, caller); @@ -143,7 +143,7 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_close channel->Close(); } -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_dispose +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCDataChannel_dispose (JNIEnv * env, jobject caller) { webrtc::DataChannelInterface * channel = GetHandle(env, caller); @@ -160,7 +160,7 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_dispose channel = nullptr; } -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_sendDirectBuffer +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCDataChannel_sendDirectBuffer (JNIEnv * env, jobject caller, jobject jBuffer, jboolean isBinary) { webrtc::DataChannelInterface * channel = GetHandle(env, caller); @@ -180,7 +180,7 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_sendDirectBuffer } } -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDataChannel_sendByteArrayBuffer +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCDataChannel_sendByteArrayBuffer (JNIEnv * env, jobject caller, jbyteArray jBufferArray, jboolean isBinary) { webrtc::DataChannelInterface * channel = GetHandle(env, caller); diff --git a/webrtc-jni/src/main/cpp/src/JNI_RTCDtlsTransport.cpp b/webrtc-jni/src/main/cpp/src/JNI_RTCDtlsTransport.cpp index 04454fb..e006c64 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_RTCDtlsTransport.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_RTCDtlsTransport.cpp @@ -25,7 +25,7 @@ #include "api/dtls_transport_interface.h" -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCDtlsTransport_getIceTransport +JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCDtlsTransport_getIceTransport (JNIEnv * env, jobject caller) { webrtc::DtlsTransportInterface * transport = GetHandle(env, caller); @@ -36,7 +36,7 @@ JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCDtlsTransport_getIceTranspor return jni::JavaFactories::create(env, iceTransport.get()).release(); } -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCDtlsTransport_getState +JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCDtlsTransport_getState (JNIEnv * env, jobject caller) { webrtc::DtlsTransportInterface * transport = GetHandle(env, caller); @@ -47,7 +47,7 @@ JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCDtlsTransport_getState return jni::JavaEnums::toJava(env, info.state()).release(); } -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCDtlsTransport_getRemoteCertificates +JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCDtlsTransport_getRemoteCertificates (JNIEnv * env, jobject caller) { webrtc::DtlsTransportInterface * transport = GetHandle(env, caller); @@ -70,7 +70,7 @@ JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCDtlsTransport_getRemoteCerti return certificates.listObject().release(); } -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDtlsTransport_registerObserver +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCDtlsTransport_registerObserver (JNIEnv * env, jobject caller, jobject observer) { webrtc::DtlsTransportInterface * transport = GetHandle(env, caller); @@ -79,7 +79,7 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDtlsTransport_registerObserver transport->RegisterObserver(new jni::RTCDtlsTransportObserver(env, jni::JavaGlobalRef(env, observer))); } -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCDtlsTransport_unregisterObserver +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCDtlsTransport_unregisterObserver (JNIEnv * env, jobject caller) { webrtc::DtlsTransportInterface * transport = GetHandle(env, caller); diff --git a/webrtc-jni/src/main/cpp/src/JNI_RTCPeerConnection.cpp b/webrtc-jni/src/main/cpp/src/JNI_RTCPeerConnection.cpp index 3c6df3a..c663124 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_RTCPeerConnection.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_RTCPeerConnection.cpp @@ -42,7 +42,7 @@ #include #include -JNIEXPORT jobjectArray JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getSenders +JNIEXPORT jobjectArray JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getSenders (JNIEnv * env, jobject caller) { webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); @@ -60,7 +60,7 @@ JNIEXPORT jobjectArray JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getSende return objectArray.release(); } -JNIEXPORT jobjectArray JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getReceivers +JNIEXPORT jobjectArray JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getReceivers (JNIEnv * env, jobject caller) { webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); @@ -78,7 +78,7 @@ JNIEXPORT jobjectArray JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getRecei return objectArray.release(); } -JNIEXPORT jobjectArray JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getTransceivers +JNIEXPORT jobjectArray JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getTransceivers (JNIEnv * env, jobject caller) { webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); @@ -96,7 +96,7 @@ JNIEXPORT jobjectArray JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getTrans return objectArray.release(); } -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_createDataChannel +JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_createDataChannel (JNIEnv * env, jobject caller, jstring jLabel, jobject jDict) { if (jLabel == nullptr) { @@ -134,7 +134,7 @@ JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_createDataCha } } -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_createOffer +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_createOffer (JNIEnv * env, jobject caller, jobject jOptions, jobject jObserver) { if (jOptions == nullptr) { @@ -160,7 +160,7 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_createOffer } } -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_createAnswer +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_createAnswer (JNIEnv * env, jobject caller, jobject jOptions, jobject jObserver) { if (jOptions == nullptr) { @@ -186,7 +186,7 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_createAnswer } } -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getCurrentLocalDescription +JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getCurrentLocalDescription (JNIEnv * env, jobject caller) { webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); @@ -199,7 +199,7 @@ JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getCurrentLoc return jni::RTCSessionDescription::toJava(env, pc->current_local_description()).release(); } -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getLocalDescription +JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getLocalDescription (JNIEnv * env, jobject caller) { webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); @@ -212,7 +212,7 @@ JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getLocalDescr return jni::RTCSessionDescription::toJava(env, pc->local_description()).release(); } -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getPendingLocalDescription +JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getPendingLocalDescription (JNIEnv * env, jobject caller) { webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); @@ -225,7 +225,7 @@ JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getPendingLoc return jni::RTCSessionDescription::toJava(env, pc->pending_local_description()).release(); } -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getCurrentRemoteDescription +JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getCurrentRemoteDescription (JNIEnv * env, jobject caller) { webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); @@ -238,7 +238,7 @@ JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getCurrentRem return jni::RTCSessionDescription::toJava(env, pc->current_remote_description()).release(); } -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getRemoteDescription +JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getRemoteDescription (JNIEnv * env, jobject caller) { webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); @@ -251,7 +251,7 @@ JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getRemoteDesc return jni::RTCSessionDescription::toJava(env, pc->remote_description()).release(); } -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getPendingRemoteDescription +JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getPendingRemoteDescription (JNIEnv * env, jobject caller) { webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); @@ -264,7 +264,7 @@ JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getPendingRem return jni::RTCSessionDescription::toJava(env, pc->pending_remote_description()).release(); } -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_setLocalDescription +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_setLocalDescription (JNIEnv * env, jobject caller, jobject jSessionDesc, jobject jobserver) { if (jSessionDesc == nullptr) { @@ -290,7 +290,7 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_setLocalDescript } } -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_setRemoteDescription +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_setRemoteDescription (JNIEnv * env, jobject caller, jobject jSessionDesc, jobject jobserver) { if (jSessionDesc == nullptr) { @@ -316,7 +316,7 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_setRemoteDescrip } } -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_addIceCandidate +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_addIceCandidate (JNIEnv * env, jobject caller, jobject jCandidate) { if (jCandidate == nullptr) { @@ -337,7 +337,7 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_addIceCandidate } } -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_removeIceCandidates +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_removeIceCandidates (JNIEnv * env, jobject caller, jobject jCandidates) { if (jCandidates == nullptr) { @@ -361,7 +361,7 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_removeIceCandida } } -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getSignalingState +JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getSignalingState (JNIEnv * env, jobject caller) { webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); @@ -370,7 +370,7 @@ JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getSignalingS return jni::JavaEnums::toJava(env, pc->signaling_state()).release(); } -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getIceGatheringState +JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getIceGatheringState (JNIEnv * env, jobject caller) { webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); @@ -379,7 +379,7 @@ JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getIceGatheri return jni::JavaEnums::toJava(env, pc->ice_gathering_state()).release(); } -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getIceConnectionState +JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getIceConnectionState (JNIEnv * env, jobject caller) { webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); @@ -388,7 +388,7 @@ JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getIceConnect return jni::JavaEnums::toJava(env, pc->ice_connection_state()).release(); } -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getConnectionState +JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getConnectionState (JNIEnv * env, jobject caller) { webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); @@ -397,7 +397,7 @@ JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getConnection return jni::JavaEnums::toJava(env, pc->peer_connection_state()).release(); } -JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getConfiguration +JNIEXPORT jobject JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getConfiguration (JNIEnv * env, jobject caller) { webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); @@ -406,7 +406,7 @@ JNIEXPORT jobject JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getConfigurat return jni::RTCConfiguration::toJava(env, pc->GetConfiguration()).release(); } -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_setConfiguration +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_setConfiguration (JNIEnv * env, jobject caller, jobject jConfig) { if (jConfig == nullptr) { @@ -426,7 +426,7 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_setConfiguration } } -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getStats__Ldev_onvoid_webrtc_RTCStatsCollectorCallback_2 +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getStats__Ldev_kastle_webrtc_RTCStatsCollectorCallback_2 (JNIEnv * env, jobject caller, jobject jcallback) { webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); @@ -442,7 +442,7 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_getStats__Ldev_o pc->GetStats(callback); } -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_restartIce +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_restartIce (JNIEnv * env, jobject caller) { webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); @@ -451,7 +451,7 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_restartIce pc->RestartIce(); } -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_RTCPeerConnection_close +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_close (JNIEnv * env, jobject caller) { webrtc::PeerConnectionInterface * pc = GetHandle(env, caller); diff --git a/webrtc-jni/src/main/cpp/src/JNI_RefCountedObject.cpp b/webrtc-jni/src/main/cpp/src/JNI_RefCountedObject.cpp index 7479124..1b15871 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_RefCountedObject.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_RefCountedObject.cpp @@ -19,7 +19,7 @@ #include "rtc_base/ref_count.h" -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_internal_RefCountedObject_retain +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_internal_RefCountedObject_retain (JNIEnv * env, jobject caller) { webrtc::RefCountInterface * ref = GetHandle(env, caller); @@ -28,7 +28,7 @@ JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_internal_RefCountedObject_retain ref->AddRef(); } -JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_internal_RefCountedObject_release +JNIEXPORT void JNICALL Java_dev_kastle_webrtc_internal_RefCountedObject_release (JNIEnv * env, jobject caller) { webrtc::RefCountInterface * ref = GetHandle(env, caller); diff --git a/webrtc/build.gradle.kts b/webrtc/build.gradle.kts index 0ad1fca..14a1881 100644 --- a/webrtc/build.gradle.kts +++ b/webrtc/build.gradle.kts @@ -22,8 +22,8 @@ tasks.named("test") { useJUnitPlatform() jvmArgs( - "--add-opens=webrtc.java/dev.onvoid.webrtc=ALL-UNNAMED", - "--add-opens=webrtc.java/dev.onvoid.webrtc.logging=ALL-UNNAMED" + "--add-opens=webrtc.java/dev.kastle.webrtc=ALL-UNNAMED", + "--add-opens=webrtc.java/dev.kastle.webrtc.logging=ALL-UNNAMED" ) testLogging { diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/CreateSessionDescriptionObserver.java b/webrtc/src/main/java/dev/kastle/webrtc/CreateSessionDescriptionObserver.java similarity index 98% rename from webrtc/src/main/java/dev/onvoid/webrtc/CreateSessionDescriptionObserver.java rename to webrtc/src/main/java/dev/kastle/webrtc/CreateSessionDescriptionObserver.java index 041775c..a18b04e 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/CreateSessionDescriptionObserver.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/CreateSessionDescriptionObserver.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * Callback interface used to obtain {@link RTCSessionDescription}s when calling diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/PeerConnectionFactory.java b/webrtc/src/main/java/dev/kastle/webrtc/PeerConnectionFactory.java similarity index 93% rename from webrtc/src/main/java/dev/onvoid/webrtc/PeerConnectionFactory.java rename to webrtc/src/main/java/dev/kastle/webrtc/PeerConnectionFactory.java index 54f3259..e2db418 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/PeerConnectionFactory.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/PeerConnectionFactory.java @@ -14,10 +14,10 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; -import dev.onvoid.webrtc.internal.DisposableNativeObject; -import dev.onvoid.webrtc.internal.NativeLoader; +import dev.kastle.webrtc.internal.DisposableNativeObject; +import dev.kastle.webrtc.internal.NativeLoader; /** * The PeerConnectionFactory is the main entry point for a WebRTC application. diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/PeerConnectionObserver.java b/webrtc/src/main/java/dev/kastle/webrtc/PeerConnectionObserver.java similarity index 99% rename from webrtc/src/main/java/dev/onvoid/webrtc/PeerConnectionObserver.java rename to webrtc/src/main/java/dev/kastle/webrtc/PeerConnectionObserver.java index 70185f2..91c19c7 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/PeerConnectionObserver.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/PeerConnectionObserver.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * RTCPeerConnection callback interface. diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/PortAllocatorConfig.java b/webrtc/src/main/java/dev/kastle/webrtc/PortAllocatorConfig.java similarity index 99% rename from webrtc/src/main/java/dev/onvoid/webrtc/PortAllocatorConfig.java rename to webrtc/src/main/java/dev/kastle/webrtc/PortAllocatorConfig.java index 5f0e578..d2b47bc 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/PortAllocatorConfig.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/PortAllocatorConfig.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * Port allocator configuration for ICE candidate gathering. diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCAnswerOptions.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCAnswerOptions.java similarity index 96% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCAnswerOptions.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCAnswerOptions.java index b3e257e..5528b43 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCAnswerOptions.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCAnswerOptions.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * The RTCAnswerOptions describe options specific to the session description of diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCBundlePolicy.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCBundlePolicy.java similarity index 98% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCBundlePolicy.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCBundlePolicy.java index 9b1b461..4a93112 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCBundlePolicy.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCBundlePolicy.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * The bundle policy affects which media tracks are negotiated if the remote diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCCertificatePEM.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCCertificatePEM.java similarity index 98% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCCertificatePEM.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCCertificatePEM.java index 96ae359..e326f36 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCCertificatePEM.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCCertificatePEM.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * Represents a certificate used to authenticate WebRTC communications. This diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCConfiguration.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCConfiguration.java similarity index 98% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCConfiguration.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCConfiguration.java index 520baaa..28c193f 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCConfiguration.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCConfiguration.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; import java.util.ArrayList; import java.util.List; diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCDataChannel.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCDataChannel.java similarity index 98% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCDataChannel.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCDataChannel.java index 87c3ec6..3da6414 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCDataChannel.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCDataChannel.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; -import dev.onvoid.webrtc.internal.DisposableNativeObject; +import dev.kastle.webrtc.internal.DisposableNativeObject; import java.nio.ByteBuffer; diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCDataChannelBuffer.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCDataChannelBuffer.java similarity index 98% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCDataChannelBuffer.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCDataChannelBuffer.java index 3829ab1..e46c144 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCDataChannelBuffer.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCDataChannelBuffer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; import java.nio.ByteBuffer; diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCDataChannelInit.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCDataChannelInit.java similarity index 98% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCDataChannelInit.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCDataChannelInit.java index a24d6d7..c20c85c 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCDataChannelInit.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCDataChannelInit.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * The RTCDataChannelInit describes options to configure a {@link diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCDataChannelObserver.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCDataChannelObserver.java similarity index 98% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCDataChannelObserver.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCDataChannelObserver.java index a248eae..b6107e8 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCDataChannelObserver.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCDataChannelObserver.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * Used to receive events from the {@link RTCDataChannel}. diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCDataChannelState.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCDataChannelState.java similarity index 97% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCDataChannelState.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCDataChannelState.java index bae6774..3e0c94e 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCDataChannelState.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCDataChannelState.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * Represents the state of the {@link RTCDataChannel}. diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCDtlsTransport.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCDtlsTransport.java similarity index 97% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCDtlsTransport.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCDtlsTransport.java index f9a71a2..f08891f 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCDtlsTransport.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCDtlsTransport.java @@ -14,11 +14,11 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; import java.util.List; -import dev.onvoid.webrtc.internal.NativeObject; +import dev.kastle.webrtc.internal.NativeObject; /** * Allows an application to access information about the Datagram Transport diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCDtlsTransportObserver.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCDtlsTransportObserver.java similarity index 97% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCDtlsTransportObserver.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCDtlsTransportObserver.java index a5b054a..25915d0 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCDtlsTransportObserver.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCDtlsTransportObserver.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * Receives events from an {@link RTCDtlsTransport}. diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCDtlsTransportState.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCDtlsTransportState.java similarity index 97% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCDtlsTransportState.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCDtlsTransportState.java index 26eb8cc..22f1ea4 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCDtlsTransportState.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCDtlsTransportState.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * Datagram Transport Layer Security (DTLS) transport states. diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCDtxStatus.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCDtxStatus.java similarity index 96% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCDtxStatus.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCDtxStatus.java index 6bb2598..b1b46b5 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCDtxStatus.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCDtxStatus.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * Represents the signaling DTX status. diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCIceCandidate.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCIceCandidate.java similarity index 98% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCIceCandidate.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCIceCandidate.java index ce17d5e..fff98c8 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCIceCandidate.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCIceCandidate.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * An ICE candidate describes the protocols and routing needed to be able to diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCIceConnectionState.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCIceConnectionState.java similarity index 98% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCIceConnectionState.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCIceConnectionState.java index 16141ef..521ca99 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCIceConnectionState.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCIceConnectionState.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * Describes the current state of the ICE agent and its connection to the ICE diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCIceGatheringState.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCIceGatheringState.java similarity index 97% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCIceGatheringState.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCIceGatheringState.java index 681b934..49c6725 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCIceGatheringState.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCIceGatheringState.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * Describes the ICE gathering state for the {@link RTCPeerConnection}. diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCIceServer.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCIceServer.java similarity index 99% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCIceServer.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCIceServer.java index 9be58ed..3c1b775 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCIceServer.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCIceServer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; import java.util.ArrayList; import java.util.List; diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCIceTransport.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCIceTransport.java similarity index 94% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCIceTransport.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCIceTransport.java index 5fc0efa..c9baab5 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCIceTransport.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCIceTransport.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; -import dev.onvoid.webrtc.internal.NativeObject; +import dev.kastle.webrtc.internal.NativeObject; /** * Allows an application access to information about the ICE transport over diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCIceTransportPolicy.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCIceTransportPolicy.java similarity index 98% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCIceTransportPolicy.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCIceTransportPolicy.java index 9279363..6a04490 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCIceTransportPolicy.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCIceTransportPolicy.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * Defines the ICE candidate policy the application uses to surface the diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCOfferAnswerOptions.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCOfferAnswerOptions.java similarity index 98% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCOfferAnswerOptions.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCOfferAnswerOptions.java index 89e730a..e6c9012 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCOfferAnswerOptions.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCOfferAnswerOptions.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * The RTCOfferAnswerOptions describe the options that can be used to control diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCOfferOptions.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCOfferOptions.java similarity index 98% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCOfferOptions.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCOfferOptions.java index 7fc8480..c81ae46 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCOfferOptions.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCOfferOptions.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * The RTCAnswerOptions describe options specific to the session description of diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCPeerConnection.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCPeerConnection.java similarity index 99% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCPeerConnection.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCPeerConnection.java index 252ad2c..47a4732 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCPeerConnection.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCPeerConnection.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; -import dev.onvoid.webrtc.internal.NativeObject; +import dev.kastle.webrtc.internal.NativeObject; /** * The RTCPeerConnection represents a WebRTC connection between the local diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCPeerConnectionIceErrorEvent.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCPeerConnectionIceErrorEvent.java similarity index 99% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCPeerConnectionIceErrorEvent.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCPeerConnectionIceErrorEvent.java index 73c8725..d3f6395 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCPeerConnectionIceErrorEvent.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCPeerConnectionIceErrorEvent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * This event occurs when the {@link RTCPeerConnection} fails to gather an ICE diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCPeerConnectionState.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCPeerConnectionState.java similarity index 98% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCPeerConnectionState.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCPeerConnectionState.java index 22ec1b0..4a272c9 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCPeerConnectionState.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCPeerConnectionState.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * Indicates the current state of the {@link RTCPeerConnection}. diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCPriorityType.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCPriorityType.java similarity index 97% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCPriorityType.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCPriorityType.java index 3231e08..9d02c1a 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCPriorityType.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCPriorityType.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * Describes the priority of media and data flows. diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtcpMuxPolicy.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCRtcpMuxPolicy.java similarity index 98% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCRtcpMuxPolicy.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCRtcpMuxPolicy.java index 4f57398..80bb638 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCRtcpMuxPolicy.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCRtcpMuxPolicy.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * The RtcpMuxPolicy affects what ICE candidates are gathered to support diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCSdpType.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCSdpType.java similarity index 98% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCSdpType.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCSdpType.java index d8dc18a..fc173e7 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCSdpType.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCSdpType.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * The RTCSdpType describes the type of an {@link RTCSessionDescription}. diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCSessionDescription.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCSessionDescription.java similarity index 98% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCSessionDescription.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCSessionDescription.java index 6a381b3..2a99f30 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCSessionDescription.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCSessionDescription.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; import java.util.Objects; diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCSignalingState.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCSignalingState.java similarity index 98% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCSignalingState.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCSignalingState.java index 6694158..486fdf6 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCSignalingState.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCSignalingState.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * Describes the state of the signaling process on the local end of the diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCStats.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCStats.java similarity index 99% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCStats.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCStats.java index fc827ef..b92c9c5 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCStats.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCStats.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; import java.util.Map; diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCStatsCollectorCallback.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCStatsCollectorCallback.java similarity index 97% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCStatsCollectorCallback.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCStatsCollectorCallback.java index 4025a81..018f4f8 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCStatsCollectorCallback.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCStatsCollectorCallback.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * An RTCStatsCollectorCallback reports back when an {@link RTCStatsReport} is diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCStatsReport.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCStatsReport.java similarity index 98% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCStatsReport.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCStatsReport.java index 86aeb03..4b59824 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCStatsReport.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCStatsReport.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; import java.util.Map; import java.util.stream.Collectors; diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/RTCStatsType.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCStatsType.java similarity index 99% rename from webrtc/src/main/java/dev/onvoid/webrtc/RTCStatsType.java rename to webrtc/src/main/java/dev/kastle/webrtc/RTCStatsType.java index 78efba7..856c59c 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/RTCStatsType.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCStatsType.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * An RTCStatsType indicates the type of the object that the {@link RTCStats} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/SetSessionDescriptionObserver.java b/webrtc/src/main/java/dev/kastle/webrtc/SetSessionDescriptionObserver.java similarity index 97% rename from webrtc/src/main/java/dev/onvoid/webrtc/SetSessionDescriptionObserver.java rename to webrtc/src/main/java/dev/kastle/webrtc/SetSessionDescriptionObserver.java index edeeecf..db6e79f 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/SetSessionDescriptionObserver.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/SetSessionDescriptionObserver.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * Callback interface used to get notified when the {@link RTCPeerConnection} diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/TlsCertPolicy.java b/webrtc/src/main/java/dev/kastle/webrtc/TlsCertPolicy.java similarity index 97% rename from webrtc/src/main/java/dev/onvoid/webrtc/TlsCertPolicy.java rename to webrtc/src/main/java/dev/kastle/webrtc/TlsCertPolicy.java index b215014..7ff16e5 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/TlsCertPolicy.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/TlsCertPolicy.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; /** * TLS certificate policy. diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/internal/DisposableNativeObject.java b/webrtc/src/main/java/dev/kastle/webrtc/internal/DisposableNativeObject.java similarity index 96% rename from webrtc/src/main/java/dev/onvoid/webrtc/internal/DisposableNativeObject.java rename to webrtc/src/main/java/dev/kastle/webrtc/internal/DisposableNativeObject.java index e2edfbc..89941d0 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/internal/DisposableNativeObject.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/internal/DisposableNativeObject.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc.internal; +package dev.kastle.webrtc.internal; /** * Allows disposing the native object bound to the Java object and free native diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/internal/NativeClassLoader.java b/webrtc/src/main/java/dev/kastle/webrtc/internal/NativeClassLoader.java similarity index 96% rename from webrtc/src/main/java/dev/onvoid/webrtc/internal/NativeClassLoader.java rename to webrtc/src/main/java/dev/kastle/webrtc/internal/NativeClassLoader.java index 59790ca..90e1e9c 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/internal/NativeClassLoader.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/internal/NativeClassLoader.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc.internal; +package dev.kastle.webrtc.internal; /** * This ClassLoader is capable of loading Java classes regardless of what thread diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/internal/NativeLoader.java b/webrtc/src/main/java/dev/kastle/webrtc/internal/NativeLoader.java similarity index 99% rename from webrtc/src/main/java/dev/onvoid/webrtc/internal/NativeLoader.java rename to webrtc/src/main/java/dev/kastle/webrtc/internal/NativeLoader.java index a46dffd..970e94e 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/internal/NativeLoader.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/internal/NativeLoader.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc.internal; +package dev.kastle.webrtc.internal; import java.io.File; import java.io.InputStream; diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/internal/NativeObject.java b/webrtc/src/main/java/dev/kastle/webrtc/internal/NativeObject.java similarity index 96% rename from webrtc/src/main/java/dev/onvoid/webrtc/internal/NativeObject.java rename to webrtc/src/main/java/dev/kastle/webrtc/internal/NativeObject.java index fa170b5..f131e7a 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/internal/NativeObject.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/internal/NativeObject.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc.internal; +package dev.kastle.webrtc.internal; /** * Binds a native object pointer to a Java object extending this class. diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/internal/RefCounted.java b/webrtc/src/main/java/dev/kastle/webrtc/internal/RefCounted.java similarity index 97% rename from webrtc/src/main/java/dev/onvoid/webrtc/internal/RefCounted.java rename to webrtc/src/main/java/dev/kastle/webrtc/internal/RefCounted.java index 8bc593f..7d8067f 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/internal/RefCounted.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/internal/RefCounted.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc.internal; +package dev.kastle.webrtc.internal; /** * Interface for ref counted objects in WebRTC. These objects have significant diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/internal/RefCountedObject.java b/webrtc/src/main/java/dev/kastle/webrtc/internal/RefCountedObject.java similarity index 95% rename from webrtc/src/main/java/dev/onvoid/webrtc/internal/RefCountedObject.java rename to webrtc/src/main/java/dev/kastle/webrtc/internal/RefCountedObject.java index b3d7a25..56abf04 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/internal/RefCountedObject.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/internal/RefCountedObject.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc.internal; +package dev.kastle.webrtc.internal; public abstract class RefCountedObject extends NativeObject implements RefCounted { diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/logging/LogSink.java b/webrtc/src/main/java/dev/kastle/webrtc/logging/LogSink.java similarity index 95% rename from webrtc/src/main/java/dev/onvoid/webrtc/logging/LogSink.java rename to webrtc/src/main/java/dev/kastle/webrtc/logging/LogSink.java index ffacecf..1ebdb56 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/logging/LogSink.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/logging/LogSink.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc.logging; +package dev.kastle.webrtc.logging; /** * Sink interface that receives WebRTC log messages. diff --git a/webrtc/src/main/java/dev/onvoid/webrtc/logging/Logging.java b/webrtc/src/main/java/dev/kastle/webrtc/logging/Logging.java similarity index 96% rename from webrtc/src/main/java/dev/onvoid/webrtc/logging/Logging.java rename to webrtc/src/main/java/dev/kastle/webrtc/logging/Logging.java index d4e6732..0d192b6 100644 --- a/webrtc/src/main/java/dev/onvoid/webrtc/logging/Logging.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/logging/Logging.java @@ -14,12 +14,12 @@ * limitations under the License. */ -package dev.onvoid.webrtc.logging; +package dev.kastle.webrtc.logging; import java.io.PrintWriter; import java.io.StringWriter; -import dev.onvoid.webrtc.internal.NativeLoader; +import dev.kastle.webrtc.internal.NativeLoader; public class Logging { diff --git a/webrtc/src/main/java/module-info.java b/webrtc/src/main/java/module-info.java index 9f74839..35b66f5 100644 --- a/webrtc/src/main/java/module-info.java +++ b/webrtc/src/main/java/module-info.java @@ -2,7 +2,7 @@ requires java.desktop; - exports dev.onvoid.webrtc; - exports dev.onvoid.webrtc.logging; + exports dev.kastle.webrtc; + exports dev.kastle.webrtc.logging; } \ No newline at end of file diff --git a/webrtc/src/main/resources/META-INF/native-image/jni-config.json b/webrtc/src/main/resources/META-INF/native-image/jni-config.json index bef170f..833666b 100644 --- a/webrtc/src/main/resources/META-INF/native-image/jni-config.json +++ b/webrtc/src/main/resources/META-INF/native-image/jni-config.json @@ -16,79 +16,79 @@ ] }, { - "name":"dev.onvoid.webrtc.RTCBundlePolicy", + "name":"dev.kastle.webrtc.RTCBundlePolicy", "methods":[{"name":"values","parameterTypes":[] }] }, { - "name":"dev.onvoid.webrtc.RTCDataChannel", + "name":"dev.kastle.webrtc.RTCDataChannel", "methods":[{"name":"","parameterTypes":[] }] }, { - "name":"dev.onvoid.webrtc.RTCDataChannelState", + "name":"dev.kastle.webrtc.RTCDataChannelState", "methods":[{"name":"values","parameterTypes":[] }] }, { - "name":"dev.onvoid.webrtc.RTCDtlsTransport", + "name":"dev.kastle.webrtc.RTCDtlsTransport", "methods":[{"name":"","parameterTypes":[] }] }, { - "name":"dev.onvoid.webrtc.RTCDtlsTransportState", + "name":"dev.kastle.webrtc.RTCDtlsTransportState", "methods":[{"name":"values","parameterTypes":[] }] }, { - "name":"dev.onvoid.webrtc.RTCDtxStatus", + "name":"dev.kastle.webrtc.RTCDtxStatus", "methods":[{"name":"values","parameterTypes":[] }] }, { - "name":"dev.onvoid.webrtc.RTCIceConnectionState", + "name":"dev.kastle.webrtc.RTCIceConnectionState", "methods":[{"name":"values","parameterTypes":[] }] }, { - "name":"dev.onvoid.webrtc.RTCIceGatheringState", + "name":"dev.kastle.webrtc.RTCIceGatheringState", "methods":[{"name":"values","parameterTypes":[] }] }, { - "name":"dev.onvoid.webrtc.RTCIceTransport", + "name":"dev.kastle.webrtc.RTCIceTransport", "methods":[{"name":"","parameterTypes":[] }] }, { - "name":"dev.onvoid.webrtc.RTCIceTransportPolicy", + "name":"dev.kastle.webrtc.RTCIceTransportPolicy", "methods":[{"name":"values","parameterTypes":[] }] }, { - "name":"dev.onvoid.webrtc.RTCPeerConnection", + "name":"dev.kastle.webrtc.RTCPeerConnection", "methods":[{"name":"","parameterTypes":[] }] }, { - "name":"dev.onvoid.webrtc.RTCPeerConnectionState", + "name":"dev.kastle.webrtc.RTCPeerConnectionState", "methods":[{"name":"values","parameterTypes":[] }] }, { - "name":"dev.onvoid.webrtc.RTCRtcpMuxPolicy", + "name":"dev.kastle.webrtc.RTCRtcpMuxPolicy", "methods":[{"name":"values","parameterTypes":[] }] }, { - "name":"dev.onvoid.webrtc.RTCSdpType", + "name":"dev.kastle.webrtc.RTCSdpType", "methods":[{"name":"values","parameterTypes":[] }] }, { - "name":"dev.onvoid.webrtc.RTCSignalingState", + "name":"dev.kastle.webrtc.RTCSignalingState", "methods":[{"name":"values","parameterTypes":[] }] }, { - "name":"dev.onvoid.webrtc.RTCStatsType", + "name":"dev.kastle.webrtc.RTCStatsType", "methods":[{"name":"values","parameterTypes":[] }] }, { - "name":"dev.onvoid.webrtc.TlsCertPolicy", + "name":"dev.kastle.webrtc.TlsCertPolicy", "methods":[{"name":"values","parameterTypes":[] }] }, { - "name":"dev.onvoid.webrtc.internal.NativeClassLoader", + "name":"dev.kastle.webrtc.internal.NativeClassLoader", "methods":[{"name":"getClassLoader","parameterTypes":[] }] }, { - "name":"dev.onvoid.webrtc.logging.Logging$Severity", + "name":"dev.kastle.webrtc.logging.Logging$Severity", "methods":[{"name":"values","parameterTypes":[] }] } ] diff --git a/webrtc/src/main/resources/META-INF/native-image/reflect-config.json b/webrtc/src/main/resources/META-INF/native-image/reflect-config.json index d468750..67a5bff 100644 --- a/webrtc/src/main/resources/META-INF/native-image/reflect-config.json +++ b/webrtc/src/main/resources/META-INF/native-image/reflect-config.json @@ -1,74 +1,74 @@ [ { - "name": "dev.onvoid.webrtc.RTCCertificatePEM" + "name": "dev.kastle.webrtc.RTCCertificatePEM" }, { - "name": "dev.onvoid.webrtc.RTCConfiguration" + "name": "dev.kastle.webrtc.RTCConfiguration" }, { - "name": "dev.onvoid.webrtc.RTCDataChannel" + "name": "dev.kastle.webrtc.RTCDataChannel" }, { - "name": "dev.onvoid.webrtc.RTCDataChannelBuffer" + "name": "dev.kastle.webrtc.RTCDataChannelBuffer" }, { - "name": "dev.onvoid.webrtc.RTCDataChannelState" + "name": "dev.kastle.webrtc.RTCDataChannelState" }, { - "name": "dev.onvoid.webrtc.RTCDtlsTransport" + "name": "dev.kastle.webrtc.RTCDtlsTransport" }, { - "name": "dev.onvoid.webrtc.RTCDtlsTransportState" + "name": "dev.kastle.webrtc.RTCDtlsTransportState" }, { - "name": "dev.onvoid.webrtc.RTCDtxStatus" + "name": "dev.kastle.webrtc.RTCDtxStatus" }, { - "name": "dev.onvoid.webrtc.RTCIceCandidate" + "name": "dev.kastle.webrtc.RTCIceCandidate" }, { - "name": "dev.onvoid.webrtc.RTCIceConnectionState" + "name": "dev.kastle.webrtc.RTCIceConnectionState" }, { - "name": "dev.onvoid.webrtc.RTCIceGatheringState" + "name": "dev.kastle.webrtc.RTCIceGatheringState" }, { - "name": "dev.onvoid.webrtc.RTCPeerConnection" + "name": "dev.kastle.webrtc.RTCPeerConnection" }, { - "name": "dev.onvoid.webrtc.RTCPeerConnectionState" + "name": "dev.kastle.webrtc.RTCPeerConnectionState" }, { - "name": "dev.onvoid.webrtc.RTCPriorityType" + "name": "dev.kastle.webrtc.RTCPriorityType" }, { - "name": "dev.onvoid.webrtc.RTCRtcpParameters" + "name": "dev.kastle.webrtc.RTCRtcpParameters" }, { - "name": "dev.onvoid.webrtc.RTCSdpType" + "name": "dev.kastle.webrtc.RTCSdpType" }, { - "name": "dev.onvoid.webrtc.RTCSessionDescription" + "name": "dev.kastle.webrtc.RTCSessionDescription" }, { - "name": "dev.onvoid.webrtc.RTCSignalingState" + "name": "dev.kastle.webrtc.RTCSignalingState" }, { - "name": "dev.onvoid.webrtc.RTCStats" + "name": "dev.kastle.webrtc.RTCStats" }, { - "name": "dev.onvoid.webrtc.RTCStatsCollectorCallback" + "name": "dev.kastle.webrtc.RTCStatsCollectorCallback" }, { - "name": "dev.onvoid.webrtc.RTCStatsReport" + "name": "dev.kastle.webrtc.RTCStatsReport" }, { - "name": "dev.onvoid.webrtc.RTCStatsType" + "name": "dev.kastle.webrtc.RTCStatsType" }, { - "name": "dev.onvoid.webrtc.TlsCertPolicy" + "name": "dev.kastle.webrtc.TlsCertPolicy" }, { - "name": "dev.onvoid.webrtc.logging.LogSink" + "name": "dev.kastle.webrtc.logging.LogSink" } ] diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/PeerConnectionFactoryTests.java b/webrtc/src/test/java/dev/kastle/webrtc/PeerConnectionFactoryTests.java similarity index 97% rename from webrtc/src/test/java/dev/onvoid/webrtc/PeerConnectionFactoryTests.java rename to webrtc/src/test/java/dev/kastle/webrtc/PeerConnectionFactoryTests.java index b624db7..3642fdd 100644 --- a/webrtc/src/test/java/dev/onvoid/webrtc/PeerConnectionFactoryTests.java +++ b/webrtc/src/test/java/dev/kastle/webrtc/PeerConnectionFactoryTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; import static org.junit.jupiter.api.Assertions.*; diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/PortAllocatorConfigIntegrationTest.java b/webrtc/src/test/java/dev/kastle/webrtc/PortAllocatorConfigIntegrationTest.java similarity index 99% rename from webrtc/src/test/java/dev/onvoid/webrtc/PortAllocatorConfigIntegrationTest.java rename to webrtc/src/test/java/dev/kastle/webrtc/PortAllocatorConfigIntegrationTest.java index 67ffba4..c2fd392 100644 --- a/webrtc/src/test/java/dev/onvoid/webrtc/PortAllocatorConfigIntegrationTest.java +++ b/webrtc/src/test/java/dev/kastle/webrtc/PortAllocatorConfigIntegrationTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; import static org.junit.jupiter.api.Assertions.*; diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/PortAllocatorConfigTests.java b/webrtc/src/test/java/dev/kastle/webrtc/PortAllocatorConfigTests.java similarity index 99% rename from webrtc/src/test/java/dev/onvoid/webrtc/PortAllocatorConfigTests.java rename to webrtc/src/test/java/dev/kastle/webrtc/PortAllocatorConfigTests.java index a3d2048..5111c1a 100644 --- a/webrtc/src/test/java/dev/onvoid/webrtc/PortAllocatorConfigTests.java +++ b/webrtc/src/test/java/dev/kastle/webrtc/PortAllocatorConfigTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; import static org.junit.jupiter.api.Assertions.*; diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/RTCConfigurationTests.java b/webrtc/src/test/java/dev/kastle/webrtc/RTCConfigurationTests.java similarity index 98% rename from webrtc/src/test/java/dev/onvoid/webrtc/RTCConfigurationTests.java rename to webrtc/src/test/java/dev/kastle/webrtc/RTCConfigurationTests.java index acb0baa..637ffb1 100644 --- a/webrtc/src/test/java/dev/onvoid/webrtc/RTCConfigurationTests.java +++ b/webrtc/src/test/java/dev/kastle/webrtc/RTCConfigurationTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; import static org.junit.jupiter.api.Assertions.*; diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/RTCDataChannelTests.java b/webrtc/src/test/java/dev/kastle/webrtc/RTCDataChannelTests.java similarity index 99% rename from webrtc/src/test/java/dev/onvoid/webrtc/RTCDataChannelTests.java rename to webrtc/src/test/java/dev/kastle/webrtc/RTCDataChannelTests.java index 3a50a60..6c68a01 100644 --- a/webrtc/src/test/java/dev/onvoid/webrtc/RTCDataChannelTests.java +++ b/webrtc/src/test/java/dev/kastle/webrtc/RTCDataChannelTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; import static java.util.Objects.nonNull; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/RTCPeerConnectionTests.java b/webrtc/src/test/java/dev/kastle/webrtc/RTCPeerConnectionTests.java similarity index 99% rename from webrtc/src/test/java/dev/onvoid/webrtc/RTCPeerConnectionTests.java rename to webrtc/src/test/java/dev/kastle/webrtc/RTCPeerConnectionTests.java index 21eb675..31d455c 100644 --- a/webrtc/src/test/java/dev/onvoid/webrtc/RTCPeerConnectionTests.java +++ b/webrtc/src/test/java/dev/kastle/webrtc/RTCPeerConnectionTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; import static org.junit.jupiter.api.Assertions.*; diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/TestBase.java b/webrtc/src/test/java/dev/kastle/webrtc/TestBase.java similarity index 97% rename from webrtc/src/test/java/dev/onvoid/webrtc/TestBase.java rename to webrtc/src/test/java/dev/kastle/webrtc/TestBase.java index 95c5960..bcdf98f 100644 --- a/webrtc/src/test/java/dev/onvoid/webrtc/TestBase.java +++ b/webrtc/src/test/java/dev/kastle/webrtc/TestBase.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/TestCreateDescObserver.java b/webrtc/src/test/java/dev/kastle/webrtc/TestCreateDescObserver.java similarity index 98% rename from webrtc/src/test/java/dev/onvoid/webrtc/TestCreateDescObserver.java rename to webrtc/src/test/java/dev/kastle/webrtc/TestCreateDescObserver.java index d3e1743..15974e5 100644 --- a/webrtc/src/test/java/dev/onvoid/webrtc/TestCreateDescObserver.java +++ b/webrtc/src/test/java/dev/kastle/webrtc/TestCreateDescObserver.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; import static java.util.Objects.nonNull; diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/TestPeerConnection.java b/webrtc/src/test/java/dev/kastle/webrtc/TestPeerConnection.java similarity index 99% rename from webrtc/src/test/java/dev/onvoid/webrtc/TestPeerConnection.java rename to webrtc/src/test/java/dev/kastle/webrtc/TestPeerConnection.java index fe134f8..0e7e8b4 100644 --- a/webrtc/src/test/java/dev/onvoid/webrtc/TestPeerConnection.java +++ b/webrtc/src/test/java/dev/kastle/webrtc/TestPeerConnection.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; import static java.util.Objects.nonNull; diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/TestSetDescObserver.java b/webrtc/src/test/java/dev/kastle/webrtc/TestSetDescObserver.java similarity index 98% rename from webrtc/src/test/java/dev/onvoid/webrtc/TestSetDescObserver.java rename to webrtc/src/test/java/dev/kastle/webrtc/TestSetDescObserver.java index fc0bc3c..9cbee9b 100644 --- a/webrtc/src/test/java/dev/onvoid/webrtc/TestSetDescObserver.java +++ b/webrtc/src/test/java/dev/kastle/webrtc/TestSetDescObserver.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package dev.onvoid.webrtc; +package dev.kastle.webrtc; import static java.util.Objects.nonNull; diff --git a/webrtc/src/test/java/dev/onvoid/webrtc/logging/LoggingTests.java b/webrtc/src/test/java/dev/kastle/webrtc/logging/LoggingTests.java similarity index 90% rename from webrtc/src/test/java/dev/onvoid/webrtc/logging/LoggingTests.java rename to webrtc/src/test/java/dev/kastle/webrtc/logging/LoggingTests.java index 17efc9a..fc4b264 100644 --- a/webrtc/src/test/java/dev/onvoid/webrtc/logging/LoggingTests.java +++ b/webrtc/src/test/java/dev/kastle/webrtc/logging/LoggingTests.java @@ -14,15 +14,15 @@ * limitations under the License. */ -package dev.onvoid.webrtc.logging; +package dev.kastle.webrtc.logging; import static org.junit.jupiter.api.Assertions.*; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import dev.onvoid.webrtc.PeerConnectionFactory; -import dev.onvoid.webrtc.logging.Logging.Severity; +import dev.kastle.webrtc.PeerConnectionFactory; +import dev.kastle.webrtc.logging.Logging.Severity; import org.junit.jupiter.api.Test; From cc6bd72f6fcf5e7ae1be144347edeb7b8227d371 Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Wed, 24 Dec 2025 13:15:53 -0800 Subject: [PATCH 40/81] Remove unused java.desktop module require Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- webrtc/src/main/java/module-info.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/webrtc/src/main/java/module-info.java b/webrtc/src/main/java/module-info.java index 35b66f5..cf6b87c 100644 --- a/webrtc/src/main/java/module-info.java +++ b/webrtc/src/main/java/module-info.java @@ -1,8 +1,4 @@ module webrtc.java { - - requires java.desktop; - exports dev.kastle.webrtc; exports dev.kastle.webrtc.logging; - } \ No newline at end of file From 590924cc4aef637011cb12e37d8f449fa89cc7a0 Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Wed, 24 Dec 2025 14:29:12 -0800 Subject: [PATCH 41/81] Remove unused c++ includes Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .../main/cpp/dependencies/jni-voithos/include/JavaArray.h | 1 - .../cpp/dependencies/jni-voithos/include/JavaBigInteger.h | 1 + .../cpp/dependencies/jni-voithos/include/JavaClassUtils.h | 1 + .../main/cpp/dependencies/jni-voithos/include/JavaContext.h | 1 - .../cpp/dependencies/jni-voithos/include/JavaPrimitive.h | 1 + .../main/cpp/dependencies/jni-voithos/include/JavaString.h | 1 + .../cpp/dependencies/jni-voithos/include/JavaThrowable.h | 2 -- .../main/cpp/dependencies/jni-voithos/include/JavaUtils.h | 4 +--- .../dependencies/jni-voithos/include/jni/windows/jni_md.h | 5 +++++ .../main/cpp/dependencies/jni-voithos/src/JavaBigInteger.cpp | 1 - .../src/main/cpp/dependencies/jni-voithos/src/JavaUtils.cpp | 3 --- webrtc-jni/src/main/cpp/include/WebRTCContext.h | 1 - webrtc-jni/src/main/cpp/include/api/RTCStats.h | 2 +- webrtc-jni/src/main/cpp/src/JNI_Logging.cpp | 2 -- webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp | 2 -- webrtc-jni/src/main/cpp/src/JNI_RTCDataChannel.cpp | 2 -- webrtc-jni/src/main/cpp/src/JNI_RTCPeerConnection.cpp | 4 ---- webrtc-jni/src/main/cpp/src/JNI_RefCountedObject.cpp | 2 +- webrtc-jni/src/main/cpp/src/WebRTCContext.cpp | 3 --- webrtc-jni/src/main/cpp/src/api/PeerConnectionObserver.cpp | 1 - webrtc-jni/src/main/cpp/src/api/RTCAnswerOptions.cpp | 3 --- webrtc-jni/src/main/cpp/src/api/RTCDataChannelObserver.cpp | 1 - webrtc-jni/src/main/cpp/src/api/RTCIceServer.cpp | 1 - webrtc-jni/src/main/cpp/src/api/RTCOfferOptions.cpp | 3 --- .../src/main/cpp/src/api/RTCPeerConnectionIceErrorEvent.cpp | 1 - webrtc-jni/src/main/cpp/src/api/RTCStats.cpp | 1 - .../src/main/cpp/src/api/RTCStatsCollectorCallback.cpp | 1 - webrtc-jni/src/main/cpp/src/rtc/RTCCertificatePEM.cpp | 3 --- .../main/java/dev/kastle/webrtc/PeerConnectionFactory.java | 3 --- .../src/main/java/dev/kastle/webrtc/RTCPeerConnection.java | 1 - 30 files changed, 12 insertions(+), 46 deletions(-) diff --git a/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaArray.h b/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaArray.h index e24591b..307204b 100644 --- a/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaArray.h +++ b/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaArray.h @@ -9,7 +9,6 @@ #define JNI_JAVA_ARRAY_H_ #include "Exception.h" -#include "JavaClass.h" #include "JavaRef.h" #include diff --git a/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaBigInteger.h b/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaBigInteger.h index 59ee0d6..77db92f 100644 --- a/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaBigInteger.h +++ b/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaBigInteger.h @@ -13,6 +13,7 @@ #include #include +#include namespace jni { diff --git a/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaClassUtils.h b/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaClassUtils.h index 736bf6e..eaa235c 100644 --- a/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaClassUtils.h +++ b/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaClassUtils.h @@ -9,6 +9,7 @@ #define JNI_JAVA_CLASS_UTILS_H_ #include "JavaRef.h" +#include "JavaClass.h" #include #include diff --git a/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaContext.h b/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaContext.h index 724ecae..2d09468 100644 --- a/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaContext.h +++ b/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaContext.h @@ -10,7 +10,6 @@ #include "JavaClassUtils.h" #include "JavaRef.h" -#include "JavaString.h" #include #include diff --git a/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaPrimitive.h b/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaPrimitive.h index d7d0393..d760090 100644 --- a/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaPrimitive.h +++ b/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaPrimitive.h @@ -12,6 +12,7 @@ #include "JavaArray.h" #include "JavaClass.h" +#include "JavaClasses.h" #include "JavaRef.h" #include "JavaUtils.h" diff --git a/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaString.h b/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaString.h index cd86700..86818bc 100644 --- a/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaString.h +++ b/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaString.h @@ -13,6 +13,7 @@ #include #include +#include namespace jni { diff --git a/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaThrowable.h b/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaThrowable.h index e907b3e..4623d50 100644 --- a/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaThrowable.h +++ b/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaThrowable.h @@ -13,8 +13,6 @@ #include #include -#include -#include namespace jni { diff --git a/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaUtils.h b/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaUtils.h index db28797..28c1305 100644 --- a/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaUtils.h +++ b/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/JavaUtils.h @@ -8,13 +8,11 @@ #ifndef JNI_JAVA_UTILS_H_ #define JNI_JAVA_UTILS_H_ -#include "JavaNullPointerException.h" +#include "JavaNullPointerException.h" // IWYU pragma: keep -#include #include #include #include -#include #define CHECK_HANDLE(handle) \ diff --git a/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/jni/windows/jni_md.h b/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/jni/windows/jni_md.h index 3808001..b94589b 100644 --- a/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/jni/windows/jni_md.h +++ b/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/jni/windows/jni_md.h @@ -30,6 +30,11 @@ #define JNIIMPORT __declspec(dllimport) #define JNICALL __stdcall +#ifndef __int64 +#include +#define __int64 int64_t +#endif + typedef long jint; typedef __int64 jlong; typedef signed char jbyte; diff --git a/webrtc-jni/src/main/cpp/dependencies/jni-voithos/src/JavaBigInteger.cpp b/webrtc-jni/src/main/cpp/dependencies/jni-voithos/src/JavaBigInteger.cpp index cbcbe4e..dd17c14 100644 --- a/webrtc-jni/src/main/cpp/dependencies/jni-voithos/src/JavaBigInteger.cpp +++ b/webrtc-jni/src/main/cpp/dependencies/jni-voithos/src/JavaBigInteger.cpp @@ -8,7 +8,6 @@ #include "JavaArray.h" #include "JavaBigInteger.h" #include "JavaClasses.h" -#include "JavaObject.h" #include "JavaString.h" #include "JavaUtils.h" diff --git a/webrtc-jni/src/main/cpp/dependencies/jni-voithos/src/JavaUtils.cpp b/webrtc-jni/src/main/cpp/dependencies/jni-voithos/src/JavaUtils.cpp index e3b3a94..8abeb6e 100644 --- a/webrtc-jni/src/main/cpp/dependencies/jni-voithos/src/JavaUtils.cpp +++ b/webrtc-jni/src/main/cpp/dependencies/jni-voithos/src/JavaUtils.cpp @@ -5,14 +5,11 @@ * found in the LICENSE file in the root of the source tree. */ -#include "Exception.h" #include "JavaUtils.h" #include "JavaClassLoader.h" #include "JavaContext.h" #include "JavaError.h" -#include "JavaIterable.h" #include "JavaIOException.h" -#include "JavaString.h" #include "JavaThreadEnv.h" #include "JavaWrappedException.h" diff --git a/webrtc-jni/src/main/cpp/include/WebRTCContext.h b/webrtc-jni/src/main/cpp/include/WebRTCContext.h index 03a78d9..83f81da 100644 --- a/webrtc-jni/src/main/cpp/include/WebRTCContext.h +++ b/webrtc-jni/src/main/cpp/include/WebRTCContext.h @@ -21,7 +21,6 @@ #include "api/environment/environment.h" #include -#include namespace jni { diff --git a/webrtc-jni/src/main/cpp/include/api/RTCStats.h b/webrtc-jni/src/main/cpp/include/api/RTCStats.h index deae15b..8cb47f4 100644 --- a/webrtc-jni/src/main/cpp/include/api/RTCStats.h +++ b/webrtc-jni/src/main/cpp/include/api/RTCStats.h @@ -20,7 +20,7 @@ #include "JavaClass.h" #include "JavaRef.h" -#include "api/stats/rtc_stats_report.h" +#include "api/stats/rtc_stats.h" #include diff --git a/webrtc-jni/src/main/cpp/src/JNI_Logging.cpp b/webrtc-jni/src/main/cpp/src/JNI_Logging.cpp index c6a9ce6..ece3425 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_Logging.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_Logging.cpp @@ -23,8 +23,6 @@ #include "rtc_base/logging.h" -#include - JNIEXPORT void JNICALL Java_dev_kastle_webrtc_logging_Logging_addLogSink (JNIEnv * env, jclass caller, jobject jseverity, jobject jsink) { diff --git a/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp b/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp index 211f34a..e5a388c 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_PeerConnectionFactory.cpp @@ -23,8 +23,6 @@ #include "JavaRuntimeException.h" #include "JavaUtils.h" -#include "api/create_peerconnection_factory.h" - JNIEXPORT void JNICALL Java_dev_kastle_webrtc_PeerConnectionFactory_initialize (JNIEnv * env, jobject caller) { diff --git a/webrtc-jni/src/main/cpp/src/JNI_RTCDataChannel.cpp b/webrtc-jni/src/main/cpp/src/JNI_RTCDataChannel.cpp index 91fce0c..b1300fb 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_RTCDataChannel.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_RTCDataChannel.cpp @@ -24,8 +24,6 @@ #include "api/data_channel_interface.h" -#include - JNIEXPORT void JNICALL Java_dev_kastle_webrtc_RTCDataChannel_registerObserver (JNIEnv * env, jobject caller, jobject jObserver) { diff --git a/webrtc-jni/src/main/cpp/src/JNI_RTCPeerConnection.cpp b/webrtc-jni/src/main/cpp/src/JNI_RTCPeerConnection.cpp index c663124..f388eec 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_RTCPeerConnection.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_RTCPeerConnection.cpp @@ -27,10 +27,7 @@ #include "api/WebRTCUtils.h" #include "JavaArray.h" #include "JavaEnums.h" -#include "JavaError.h" #include "JavaFactories.h" -#include "JavaIterable.h" -#include "JavaList.h" #include "JavaNullPointerException.h" #include "JavaRef.h" #include "JavaRuntimeException.h" @@ -40,7 +37,6 @@ #include "api/peer_connection_interface.h" #include -#include JNIEXPORT jobjectArray JNICALL Java_dev_kastle_webrtc_RTCPeerConnection_getSenders (JNIEnv * env, jobject caller) diff --git a/webrtc-jni/src/main/cpp/src/JNI_RefCountedObject.cpp b/webrtc-jni/src/main/cpp/src/JNI_RefCountedObject.cpp index 1b15871..51863ac 100644 --- a/webrtc-jni/src/main/cpp/src/JNI_RefCountedObject.cpp +++ b/webrtc-jni/src/main/cpp/src/JNI_RefCountedObject.cpp @@ -17,7 +17,7 @@ #include "JNI_RefCountedObject.h" #include "JavaUtils.h" -#include "rtc_base/ref_count.h" +#include "rtc_base/ref_count.h" // IWYU pragma: keep JNIEXPORT void JNICALL Java_dev_kastle_webrtc_internal_RefCountedObject_retain (JNIEnv * env, jobject caller) diff --git a/webrtc-jni/src/main/cpp/src/WebRTCContext.cpp b/webrtc-jni/src/main/cpp/src/WebRTCContext.cpp index 4cd5e04..90271d1 100644 --- a/webrtc-jni/src/main/cpp/src/WebRTCContext.cpp +++ b/webrtc-jni/src/main/cpp/src/WebRTCContext.cpp @@ -15,7 +15,6 @@ */ #include "WebRTCContext.h" -#include "api/DataBufferFactory.h" #include "api/RTCStats.h" #include "Exception.h" #include "JavaClassLoader.h" @@ -29,8 +28,6 @@ #include "api/peer_connection_interface.h" #include "rtc_base/ssl_adapter.h" -#include - namespace jni { WebRTCContext::WebRTCContext(JavaVM * vm) : diff --git a/webrtc-jni/src/main/cpp/src/api/PeerConnectionObserver.cpp b/webrtc-jni/src/main/cpp/src/api/PeerConnectionObserver.cpp index c1b7b56..31ceb99 100644 --- a/webrtc-jni/src/main/cpp/src/api/PeerConnectionObserver.cpp +++ b/webrtc-jni/src/main/cpp/src/api/PeerConnectionObserver.cpp @@ -17,7 +17,6 @@ #include "api/PeerConnectionObserver.h" #include "api/RTCIceCandidate.h" #include "api/RTCPeerConnectionIceErrorEvent.h" -#include "api/WebRTCUtils.h" #include "Exception.h" #include "JavaArray.h" #include "JavaClasses.h" diff --git a/webrtc-jni/src/main/cpp/src/api/RTCAnswerOptions.cpp b/webrtc-jni/src/main/cpp/src/api/RTCAnswerOptions.cpp index 0cf85eb..ae18aa5 100644 --- a/webrtc-jni/src/main/cpp/src/api/RTCAnswerOptions.cpp +++ b/webrtc-jni/src/main/cpp/src/api/RTCAnswerOptions.cpp @@ -16,10 +16,7 @@ #include "api/RTCAnswerOptions.h" #include "JavaClasses.h" -#include "JavaEnums.h" #include "JavaObject.h" -#include "JavaString.h" -#include "Exception.h" #include "JNI_WebRTC.h" namespace jni diff --git a/webrtc-jni/src/main/cpp/src/api/RTCDataChannelObserver.cpp b/webrtc-jni/src/main/cpp/src/api/RTCDataChannelObserver.cpp index fef868e..c93c29f 100644 --- a/webrtc-jni/src/main/cpp/src/api/RTCDataChannelObserver.cpp +++ b/webrtc-jni/src/main/cpp/src/api/RTCDataChannelObserver.cpp @@ -15,7 +15,6 @@ */ #include "api/RTCDataChannelObserver.h" -#include "JavaFactories.h" #include "JavaUtils.h" #include "JNI_WebRTC.h" diff --git a/webrtc-jni/src/main/cpp/src/api/RTCIceServer.cpp b/webrtc-jni/src/main/cpp/src/api/RTCIceServer.cpp index 08866fb..e1e62ca 100644 --- a/webrtc-jni/src/main/cpp/src/api/RTCIceServer.cpp +++ b/webrtc-jni/src/main/cpp/src/api/RTCIceServer.cpp @@ -18,7 +18,6 @@ #include "JavaArrayList.h" #include "JavaClasses.h" #include "JavaEnums.h" -#include "JavaIterable.h" #include "JavaList.h" #include "JavaRef.h" #include "JavaObject.h" diff --git a/webrtc-jni/src/main/cpp/src/api/RTCOfferOptions.cpp b/webrtc-jni/src/main/cpp/src/api/RTCOfferOptions.cpp index d009a12..e7d95c8 100644 --- a/webrtc-jni/src/main/cpp/src/api/RTCOfferOptions.cpp +++ b/webrtc-jni/src/main/cpp/src/api/RTCOfferOptions.cpp @@ -16,10 +16,7 @@ #include "api/RTCOfferOptions.h" #include "JavaClasses.h" -#include "JavaEnums.h" #include "JavaObject.h" -#include "JavaString.h" -#include "Exception.h" #include "JNI_WebRTC.h" namespace jni diff --git a/webrtc-jni/src/main/cpp/src/api/RTCPeerConnectionIceErrorEvent.cpp b/webrtc-jni/src/main/cpp/src/api/RTCPeerConnectionIceErrorEvent.cpp index 3f11bd3..64d764b 100644 --- a/webrtc-jni/src/main/cpp/src/api/RTCPeerConnectionIceErrorEvent.cpp +++ b/webrtc-jni/src/main/cpp/src/api/RTCPeerConnectionIceErrorEvent.cpp @@ -17,7 +17,6 @@ #include "api/RTCPeerConnectionIceErrorEvent.h" #include "JavaClasses.h" #include "JavaString.h" -#include "JavaObject.h" #include "JavaPrimitive.h" #include "JavaUtils.h" #include "JNI_WebRTC.h" diff --git a/webrtc-jni/src/main/cpp/src/api/RTCStats.cpp b/webrtc-jni/src/main/cpp/src/api/RTCStats.cpp index 0ee6f49..7fd59fe 100644 --- a/webrtc-jni/src/main/cpp/src/api/RTCStats.cpp +++ b/webrtc-jni/src/main/cpp/src/api/RTCStats.cpp @@ -25,7 +25,6 @@ #include "api/stats/attribute.h" #include "rtc_base/logging.h" -#include "rtc_base/string_encode.h" #include #include diff --git a/webrtc-jni/src/main/cpp/src/api/RTCStatsCollectorCallback.cpp b/webrtc-jni/src/main/cpp/src/api/RTCStatsCollectorCallback.cpp index c6e152b..7d466bf 100644 --- a/webrtc-jni/src/main/cpp/src/api/RTCStatsCollectorCallback.cpp +++ b/webrtc-jni/src/main/cpp/src/api/RTCStatsCollectorCallback.cpp @@ -16,7 +16,6 @@ #include "api/RTCStatsCollectorCallback.h" #include "api/RTCStatsReport.h" -#include "api/WebRTCUtils.h" #include "JNI_WebRTC.h" namespace jni diff --git a/webrtc-jni/src/main/cpp/src/rtc/RTCCertificatePEM.cpp b/webrtc-jni/src/main/cpp/src/rtc/RTCCertificatePEM.cpp index fe5f114..49101a7 100644 --- a/webrtc-jni/src/main/cpp/src/rtc/RTCCertificatePEM.cpp +++ b/webrtc-jni/src/main/cpp/src/rtc/RTCCertificatePEM.cpp @@ -20,9 +20,6 @@ #include "JavaString.h" #include "JNI_WebRTC.h" -#include "rtc_base/ref_count.h" -#include "rtc_base/rtc_certificate_generator.h" - namespace jni { namespace RTCCertificatePEM diff --git a/webrtc/src/main/java/dev/kastle/webrtc/PeerConnectionFactory.java b/webrtc/src/main/java/dev/kastle/webrtc/PeerConnectionFactory.java index e2db418..1ed994b 100644 --- a/webrtc/src/main/java/dev/kastle/webrtc/PeerConnectionFactory.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/PeerConnectionFactory.java @@ -37,13 +37,10 @@ public class PeerConnectionFactory extends DisposableNativeObject { } - @SuppressWarnings("unused") private long networkThreadHandle; - @SuppressWarnings("unused") private long signalingThreadHandle; - @SuppressWarnings("unused") private long workerThreadHandle; diff --git a/webrtc/src/main/java/dev/kastle/webrtc/RTCPeerConnection.java b/webrtc/src/main/java/dev/kastle/webrtc/RTCPeerConnection.java index 47a4732..afb657d 100644 --- a/webrtc/src/main/java/dev/kastle/webrtc/RTCPeerConnection.java +++ b/webrtc/src/main/java/dev/kastle/webrtc/RTCPeerConnection.java @@ -31,7 +31,6 @@ public class RTCPeerConnection extends NativeObject { * The PeerConnection doesn't take ownership of the observer. When the * PeerConnection is closed the observer will be disposed using this handle. */ - @SuppressWarnings("unused") private long observerHandle; From 946db198434faa116e7b494c175f1636216ab616 Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Wed, 24 Dec 2025 17:11:38 -0800 Subject: [PATCH 42/81] Modify gradle build Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- webrtc-jni/build.gradle.kts | 34 ++++++++++++++++++++-------------- webrtc/build.gradle.kts | 6 +----- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/webrtc-jni/build.gradle.kts b/webrtc-jni/build.gradle.kts index 61efc21..8abc883 100644 --- a/webrtc-jni/build.gradle.kts +++ b/webrtc-jni/build.gradle.kts @@ -11,24 +11,30 @@ java { } val currentOs = OperatingSystem.current() -val rawArch = System.getProperty("os.arch").lowercase().trim() -val osFamily = when { - currentOs.isLinux -> "linux" - currentOs.isMacOsX -> "macos" - currentOs.isWindows -> "windows" - else -> error("Unsupported OS: ${currentOs.name}") -} +var targetPlatform = System.getenv("WEBRTC_PLATFORM") as? String + +if (targetPlatform == null) { + val rawArch = System.getProperty("os.arch").lowercase().trim() + + val osFamily = when { + currentOs.isLinux -> "linux" + currentOs.isMacOsX -> "macos" + currentOs.isWindows -> "windows" + else -> error("Unsupported OS: ${currentOs.name}") + } + + val osArch = when { + rawArch == "amd64" || rawArch == "x86_64" || rawArch == "x86-64" -> "x86_64" + rawArch == "aarch64" || rawArch == "arm64" -> "aarch64" + rawArch.startsWith("arm") -> "aarch32" + else -> error("Unsupported Architecture: $rawArch") + } -val osArch = when { - rawArch == "amd64" || rawArch == "x86_64" || rawArch == "x86-64" -> "x86_64" - rawArch == "aarch64" || rawArch == "arm64" -> "aarch64" - rawArch.startsWith("arm") -> "aarch32" - else -> error("Unsupported Architecture: $rawArch") + targetPlatform = "$osFamily-$osArch" } -val targetPlatform = (System.getenv("WEBRTC_PLATFORM") as? String) ?: "$osFamily-$osArch" -val platformClassifier = targetPlatform.replace("_", "-") +val platformClassifier = targetPlatform?.replace("_", "-") logger.lifecycle("Configuring webrtc-jni for Platform: $targetPlatform") diff --git a/webrtc/build.gradle.kts b/webrtc/build.gradle.kts index 14a1881..d499ae8 100644 --- a/webrtc/build.gradle.kts +++ b/webrtc/build.gradle.kts @@ -16,16 +16,12 @@ configure { toolchain.languageVersion.set(JavaLanguageVersion.of(17)) withJavadocJar() withSourcesJar() + modularity.inferModulePath.set(true) } tasks.named("test") { useJUnitPlatform() - jvmArgs( - "--add-opens=webrtc.java/dev.kastle.webrtc=ALL-UNNAMED", - "--add-opens=webrtc.java/dev.kastle.webrtc.logging=ALL-UNNAMED" - ) - testLogging { events("passed", "skipped", "failed") } From 971ffee9a9321d3a37cc2fe5252fd80ca0a51416 Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Thu, 25 Dec 2025 14:39:07 -0800 Subject: [PATCH 43/81] New build system Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/build-macos-x86_64/action.yml | 76 --- .github/actions/build/action.yml | 84 +--- .github/actions/prepare-linux/action.yml | 8 +- .github/actions/prepare-macos/action.yml | 4 +- .github/actions/prepare-windows/action.yml | 36 +- .../actions/release-macos-x86_64/action.yml | 74 --- .github/actions/release/action.yml | 88 ---- .github/changelog/cliff-release.toml | 97 ---- .github/changelog/cliff.toml | 94 ---- .github/funding.yml | 1 - .github/workflows/build.yml | 58 +-- .github/workflows/pages.yml | 62 --- .github/workflows/release.yml | 275 ----------- CHANGELOG.md | 447 ------------------ gradle.properties | 1 - webrtc-jni/build.gradle.kts | 2 +- webrtc-jni/gradle.properties | 1 + 17 files changed, 54 insertions(+), 1354 deletions(-) delete mode 100644 .github/actions/build-macos-x86_64/action.yml delete mode 100644 .github/actions/release-macos-x86_64/action.yml delete mode 100644 .github/actions/release/action.yml delete mode 100644 .github/changelog/cliff-release.toml delete mode 100644 .github/changelog/cliff.toml delete mode 100644 .github/funding.yml delete mode 100644 .github/workflows/pages.yml delete mode 100644 .github/workflows/release.yml delete mode 100644 CHANGELOG.md create mode 100644 webrtc-jni/gradle.properties diff --git a/.github/actions/build-macos-x86_64/action.yml b/.github/actions/build-macos-x86_64/action.yml deleted file mode 100644 index 924ff25..0000000 --- a/.github/actions/build-macos-x86_64/action.yml +++ /dev/null @@ -1,76 +0,0 @@ -name: 'Maven Build' - -description: 'Build the platform dependent Java library' - -inputs: - java-version: - description: 'The Java build version.' - required: true - default: '17' - - platform-name: - description: 'The target platform.' - required: true - - maven-username: - description: 'The Maven username.' - required: true - - maven-password: - description: 'The Maven password.' - required: true - -runs: - using: "composite" - steps: - - name: Set up WebRTC cache - uses: actions/cache@v4 - with: - path: ${{ env.WEBRTC_CHECKOUT_FOLDER }}/build - key: webrtc-${{ env.WEBRTC_CACHE_BRANCH }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/pom.xml') }} - restore-keys: webrtc-${{ env.WEBRTC_CACHE_BRANCH }}-${{ inputs.platform-name }}- - - - name: Set up Maven cache - uses: actions/cache@v4 - with: - path: ~/.m2/repository - key: maven-${{ inputs.platform-name }}-${{ hashFiles('**/pom.xml') }} - restore-keys: maven-${{ inputs.platform-name }}- - - - name: Set up JDK - uses: actions/setup-java@v5 - with: - architecture: 'x64' - java-version: ${{ inputs.java-version }} - distribution: 'temurin' - server-id: central - server-username: MAVEN_USERNAME - server-password: MAVEN_TOKEN - - - name: Build - run: arch -x86_64 mvn package -DskipTests -Pmacos-cross-x86_64 - shell: bash - - - name: Test - run: arch -x86_64 mvn -B jar:jar surefire:test -Pmacos-cross-x86_64 - shell: bash - - - name: Archive webrtc-java - uses: actions/upload-artifact@v5 - with: - name: webrtc-java-${{ inputs.platform-name }} - path: webrtc/target/*.jar - - - name: Archive webrtc-java-jni - uses: actions/upload-artifact@v5 - with: - name: webrtc-java-jni-${{ inputs.platform-name }} - path: webrtc-jni/target/*.jar - - - name: Deploy - if: ${{ github.event_name != 'pull_request' && github.repository == 'devopvoid/webrtc-java' }} - env: - MAVEN_USERNAME: ${{ inputs.maven-username }} - MAVEN_TOKEN: ${{ inputs.maven-password }} - run: arch -x86_64 mvn deploy -DskipTests -Pmacos-cross-x86_64 - shell: bash diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index 47557d8..3960ab2 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -1,90 +1,52 @@ -name: 'Maven Build' +name: "Maven Build" -description: 'Build the platform dependent Java library' +description: "Build the platform dependent Java library" inputs: java-version: - description: 'The Java build version.' + description: "The Java build version." required: true - default: '17' + default: "17" platform-name: - description: 'The target platform.' - required: true - - maven-username: - description: 'The Maven username.' - required: true - - maven-password: - description: 'The Maven password.' + description: "The target platform." required: true runs: using: "composite" steps: - name: Set up WebRTC cache - uses: actions/cache@v4 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb + # https://github.com/actions/cache/releases/latest with: path: ${{ env.WEBRTC_CHECKOUT_FOLDER }}/build - key: webrtc-${{ env.WEBRTC_CACHE_BRANCH }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/pom.xml') }} - restore-keys: webrtc-${{ env.WEBRTC_CACHE_BRANCH }}-${{ inputs.platform-name }}- + key: webrtc-${{ hashFiles('webrtc-jni/gradle.properties') }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt') }} + restore-keys: webrtc-${{ hashFiles('webrtc-jni/gradle.properties') }}-${{ inputs.platform-name }}- - - name: Set up Maven cache - uses: actions/cache@v4 - with: - path: ~/.m2/repository - key: maven-${{ inputs.platform-name }}-${{ hashFiles('**/pom.xml') }} - restore-keys: maven-${{ inputs.platform-name }}- - - - name: Set up JDK ${{ inputs.java-version }} - uses: actions/setup-java@v5 + - uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e + # https://github.com/actions/setup-java/releases/latest with: java-version: ${{ inputs.java-version }} - distribution: 'temurin' - server-id: central - server-username: MAVEN_USERNAME - server-password: MAVEN_TOKEN - - name: Build - run: | - if [ "${{ inputs.platform-name }}" == "linux_arm" ]; then - mvn package -DskipTests -Plinux-aarch32 - elif [ "${{ inputs.platform-name }}" == "linux_arm64" ]; then - mvn package -DskipTests -Plinux-aarch64 - else - mvn package -DskipTests - fi - shell: bash + - uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 + # https://github.com/gradle/actions/releases/latest - - name: Test - if: ${{ inputs.platform-name != 'linux_arm' && inputs.platform-name != 'linux_arm64' }} - run: mvn -B jar:jar surefire:test + - name: Build + env: + WEBRTC_PLATFORM: ${{ inputs.platform-name }} + run: ./gradlew build shell: bash - name: Archive webrtc-java - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f + # https://github.com/actions/upload-artifact/releases/latest with: name: webrtc-java-${{ inputs.platform-name }} - path: webrtc/target/*.jar + path: webrtc/build/libs/*.jar - name: Archive webrtc-java-jni - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f + # https://github.com/actions/upload-artifact/releases/latest with: name: webrtc-java-jni-${{ inputs.platform-name }} - path: webrtc-jni/target/*.jar - - - name: Deploy - if: ${{ github.event_name != 'pull_request' && github.repository == 'devopvoid/webrtc-java' }} - env: - MAVEN_USERNAME: ${{ inputs.maven-username }} - MAVEN_TOKEN: ${{ inputs.maven-password }} - run: | - if [ "${{ inputs.platform-name }}" == "linux_arm" ]; then - mvn deploy -DskipTests -Plinux-aarch32 - elif [ "${{ inputs.platform-name }}" == "linux_arm64" ]; then - mvn deploy -DskipTests -Plinux-aarch64 - else - mvn deploy -DskipTests - fi - shell: bash + path: webrtc-jni/build/libs/*.jar diff --git a/.github/actions/prepare-linux/action.yml b/.github/actions/prepare-linux/action.yml index cde04ac..3d8c223 100644 --- a/.github/actions/prepare-linux/action.yml +++ b/.github/actions/prepare-linux/action.yml @@ -1,6 +1,6 @@ -name: 'Prepare Linux Build' +name: "Prepare Linux Build" -description: 'Frees up disk space and installs required packages for Linux builds.' +description: "Frees up disk space and installs required packages for Linux builds." runs: using: "composite" @@ -53,7 +53,7 @@ runs: if: matrix.platform.name == 'linux_arm' run: | sudo apt install -y gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf - + sudo mkdir /opt/sysroot python3 webrtc-jni/src/main/cpp/dependencies/webrtc/linux/sysroot/install-sysroot.py --arch=armhf sudo mv webrtc-jni/src/main/cpp/dependencies/webrtc/linux/debian* /opt/sysroot/ @@ -63,7 +63,7 @@ runs: if: matrix.platform.name == 'linux_arm64' run: | sudo apt install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu - + sudo mkdir /opt/sysroot python3 webrtc-jni/src/main/cpp/dependencies/webrtc/linux/sysroot/install-sysroot.py --arch=arm64 sudo mv webrtc-jni/src/main/cpp/dependencies/webrtc/linux/debian* /opt/sysroot/ diff --git a/.github/actions/prepare-macos/action.yml b/.github/actions/prepare-macos/action.yml index 818e04e..58733af 100644 --- a/.github/actions/prepare-macos/action.yml +++ b/.github/actions/prepare-macos/action.yml @@ -6,9 +6,7 @@ runs: using: "composite" steps: - name: Install required packages - run: | - # Required on macos-14 - brew install python-setuptools + run: brew install python-setuptools shell: bash - name: Select Xcode version diff --git a/.github/actions/prepare-windows/action.yml b/.github/actions/prepare-windows/action.yml index ff9b023..86e3b45 100644 --- a/.github/actions/prepare-windows/action.yml +++ b/.github/actions/prepare-windows/action.yml @@ -1,40 +1,10 @@ -name: 'Prepare Windows Build' +name: "Prepare Windows Build" -description: 'Frees up disk space and installs required packages for Windows builds.' +description: "Installs required packages for Windows builds." runs: using: "composite" steps: - - name: Set up Python 3.11 - if: false - uses: actions/setup-python@v5 - with: - python-version: "3.11" - - - name: Disk cleanup - if: false - run: | - Get-PSDrive - # Docker Images - docker rmi $(docker images -q -a) - # Android SDK - if ($Env:ANDROID_HOME) { - Remove-Item -Recurse -Force $Env:ANDROID_HOME -ErrorAction Ignore - } - if ($Env:ANDROID_NDK_HOME) { - Remove-Item -Recurse -Force $Env:ANDROID_NDK_HOME -ErrorAction Ignore - } - # JVM - if ($Env:JAVA_HOME_11_X64) { - Remove-Item -Recurse -Force $Env:JAVA_HOME_11_X64 -ErrorAction Ignore - } - if ($Env:JAVA_HOME_8_X64) { - Remove-Item -Recurse -Force $Env:JAVA_HOME_8_X64 -ErrorAction Ignore - } - Get-PSDrive - shell: powershell - - name: Install required packages - run: | - choco install ninja + run: choco install ninja shell: powershell diff --git a/.github/actions/release-macos-x86_64/action.yml b/.github/actions/release-macos-x86_64/action.yml deleted file mode 100644 index 1180eec..0000000 --- a/.github/actions/release-macos-x86_64/action.yml +++ /dev/null @@ -1,74 +0,0 @@ -name: 'Maven Release' - -description: 'Release the platform dependent Java library' - -inputs: - java-version: - description: 'The Java build version.' - required: true - default: '17' - - platform-name: - description: 'The target platform.' - required: true - - maven-gpg-private-key: - description: 'The GPG private key to sign Maven artifacts.' - required: true - - maven-gpg-passphrase: - description: 'The GPG passphrase for the GPG key.' - required: true - - maven-username: - description: 'The Maven username.' - required: true - - maven-password: - description: 'The Maven password.' - required: true - -runs: - using: "composite" - steps: - - name: Set up WebRTC cache - uses: actions/cache@v4 - with: - path: ${{ env.WEBRTC_CHECKOUT_FOLDER }}/build - key: webrtc-${{ env.WEBRTC_CACHE_BRANCH }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/pom.xml') }} - restore-keys: webrtc-${{ env.WEBRTC_CACHE_BRANCH }}-${{ inputs.platform-name }}- - - - name: Set up Maven cache - uses: actions/cache@v4 - with: - path: ~/.m2/repository - key: maven-${{ inputs.platform-name }}-${{ hashFiles('**/pom.xml') }} - restore-keys: maven-${{ inputs.platform-name }}- - - - name: Set up JDK ${{ inputs.java-version }} - uses: actions/setup-java@v5 - with: - architecture: 'x64' - java-version: ${{ inputs.java-version }} - distribution: 'temurin' - server-id: central - server-username: MAVEN_USERNAME - server-password: MAVEN_TOKEN - gpg-private-key: ${{ inputs.maven-gpg-private-key }} - gpg-passphrase: MAVEN_GPG_PASSPHRASE - - - name: Build - run: arch -x86_64 mvn package -DskipTests -Pmacos-cross-x86_64 - shell: bash - - - name: Test - run: arch -x86_64 mvn -B jar:jar surefire:test -Pmacos-cross-x86_64 - shell: bash - - - name: Deploy - env: - MAVEN_USERNAME: ${{ inputs.maven-username }} - MAVEN_TOKEN: ${{ inputs.maven-password }} - MAVEN_GPG_PASSPHRASE: ${{ inputs.maven-gpg-passphrase }} - run: arch -x86_64 mvn deploy -DskipTests -Pmacos-cross-x86_64 -Prelease - shell: bash diff --git a/.github/actions/release/action.yml b/.github/actions/release/action.yml deleted file mode 100644 index f7a950f..0000000 --- a/.github/actions/release/action.yml +++ /dev/null @@ -1,88 +0,0 @@ -name: 'Maven Release' - -description: 'Release the platform dependent Java library' - -inputs: - java-version: - description: 'The Java build version.' - required: true - default: '17' - - platform-name: - description: 'The target platform.' - required: true - - maven-gpg-private-key: - description: 'The GPG private key to sign Maven artifacts.' - required: true - - maven-gpg-passphrase: - description: 'The GPG passphrase for the GPG key.' - required: true - - maven-username: - description: 'The Maven username.' - required: true - - maven-password: - description: 'The Maven password.' - required: true - -runs: - using: "composite" - steps: - - name: Set up WebRTC cache - uses: actions/cache@v4 - with: - path: ${{ env.WEBRTC_CHECKOUT_FOLDER }}/build - key: webrtc-${{ env.WEBRTC_CACHE_BRANCH }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/pom.xml') }} - restore-keys: webrtc-${{ env.WEBRTC_CACHE_BRANCH }}-${{ inputs.platform-name }}- - - - name: Set up Maven cache - uses: actions/cache@v4 - with: - path: ~/.m2/repository - key: maven-${{ inputs.platform-name }}-${{ hashFiles('**/pom.xml') }} - restore-keys: maven-${{ inputs.platform-name }}- - - - name: Set up JDK ${{ inputs.java-version }} - uses: actions/setup-java@v5 - with: - java-version: ${{ inputs.java-version }} - distribution: 'temurin' - server-id: central - server-username: MAVEN_USERNAME - server-password: MAVEN_TOKEN - gpg-private-key: ${{ inputs.maven-gpg-private-key }} - gpg-passphrase: MAVEN_GPG_PASSPHRASE - - - name: Build - run: | - if [ "${{ inputs.platform-name }}" == "linux_arm" ]; then - mvn package -DskipTests -Plinux-aarch32 - elif [ "${{ inputs.platform-name }}" == "linux_arm64" ]; then - mvn package -DskipTests -Plinux-aarch64 - else - mvn package -DskipTests - fi - shell: bash - - - name: Test - if: ${{ inputs.platform-name != 'linux_arm' && inputs.platform-name != 'linux_arm64' }} - run: mvn -B jar:jar surefire:test - shell: bash - - - name: Deploy - env: - MAVEN_USERNAME: ${{ inputs.maven-username }} - MAVEN_TOKEN: ${{ inputs.maven-password }} - MAVEN_GPG_PASSPHRASE: ${{ inputs.maven-gpg-passphrase }} - run: | - if [ "${{ inputs.platform-name }}" == "linux_arm" ]; then - mvn deploy -DskipTests -Prelease -Plinux-aarch32 - elif [ "${{ inputs.platform-name }}" == "linux_arm64" ]; then - mvn deploy -DskipTests -Prelease -Plinux-aarch64 - else - mvn deploy -DskipTests -Prelease - fi - shell: bash diff --git a/.github/changelog/cliff-release.toml b/.github/changelog/cliff-release.toml deleted file mode 100644 index 63167b6..0000000 --- a/.github/changelog/cliff-release.toml +++ /dev/null @@ -1,97 +0,0 @@ -# git-cliff ~ configuration file -# https://git-cliff.org/docs/configuration - -[changelog] -# A Tera template to be rendered as the changelog's header. -# See https://keats.github.io/tera/docs/#introduction -header = """ -## What's Changed -""" -# A Tera template to be rendered for each release in the changelog. -# See https://keats.github.io/tera/docs/#introduction -body = """ -{%- macro remote_url() -%} - https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }} -{%- endmacro -%} - -{% for group, commits in commits | group_by(attribute="group") %} - ### {{ group | striptags | trim | upper_first }} - {%- for commit in commits %} - - {{ commit.message | split(pat="\n") | first | upper_first | trim }}\ - {% if commit.remote.username and commit.remote.pr_number %} by @{{ commit.remote.username }}{%- endif -%} - {% if commit.remote.pr_number %} in \ - [#{{ commit.remote.pr_number }}]({{ self::remote_url() }}/pull/{{ commit.remote.pr_number }}) \ - {%- endif -%} - {% endfor %} -{% endfor %} - -{%- if github.contributors | filter(attribute="is_first_time", value=true) | length != 0 %} - ## New Contributors -{%- endif -%} - -{% for contributor in github.contributors | filter(attribute="is_first_time", value=true) %} - * @{{ contributor.username }} made their first contribution - {%- if contributor.pr_number %} in \ - [#{{ contributor.pr_number }}]({{ self::remote_url() }}/pull/{{ contributor.pr_number }}) \ - {%- endif %} -{%- endfor %}\n -""" -# A Tera template to be rendered as the changelog's footer. -# See https://keats.github.io/tera/docs/#introduction -footer = """ -{%- macro remote_url() -%} - https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }} -{%- endmacro -%} - -{% for release in releases -%} - {% if release.version -%} - {% if release.previous.version -%} - [{{ release.version | trim_start_matches(pat="v") }}]: \ - {{ self::remote_url() }}/compare/{{ release.previous.version }}..{{ release.version }} - {% endif -%} - {% else -%} - [unreleased]: {{ self::remote_url() }}/compare/{{ release.previous.version }}..HEAD - {% endif -%} -{% endfor %} -""" -# Remove leading and trailing whitespaces from the changelog's body. -trim = true - -[git] -# Parse commits according to the conventional commits specification. -# See https://www.conventionalcommits.org -conventional_commits = true -# Exclude commits that do not match the conventional commits specification. -filter_unconventional = true -# An array of regex based parsers to modify commit messages prior to further processing. -commit_preprocessors = [ - # Remove issue numbers. - { pattern = '\((\w+\s)?#([0-9]+)\)', replace = "" }, -] -# An array of regex based parsers for extracting data from the commit message. -# Assigns commits to groups. -# Optionally sets the commit's scope and can decide to exclude commits from further processing. -commit_parsers = [ - { message = "^feat", group = "Features" }, - { message = "^fix", group = "Bug Fixes" }, - { message = "^doc", group = "Documentation" }, - { message = "^perf", group = "Performance" }, - { message = "^refactor", group = "Refactor" }, - { message = "^style", group = "Styling" }, - { message = "^test", group = "Testing" }, - { message = "^chore\\(release\\): prepare for", skip = true }, - { message = "^chore\\(deps.*\\)", skip = true }, - { message = "^chore\\(pr\\)", skip = true }, - { message = "^chore\\(pull\\)", skip = true }, - { message = "^chore|^ci", group = "Miscellaneous Tasks" }, - { body = ".*security", group = "Security" }, - { message = "^revert", group = "Revert" }, - { message = ".*", group = "Other" }, -] -# Exclude commits that are not matched by any commit parser. -filter_commits = false -# Order releases topologically instead of chronologically. -topo_order = false -# Order of commits in each group/release within the changelog. -# Allowed values: newest, oldest -sort_commits = "newest" diff --git a/.github/changelog/cliff.toml b/.github/changelog/cliff.toml deleted file mode 100644 index 75fa08d..0000000 --- a/.github/changelog/cliff.toml +++ /dev/null @@ -1,94 +0,0 @@ -# git-cliff ~ configuration file -# https://git-cliff.org/docs/configuration - -[changelog] -# A Tera template to be rendered as the changelog's header. -# See https://keats.github.io/tera/docs/#introduction -header = """ -# Changelog\n -All notable changes to this project will be documented in this file.\n -""" -# A Tera template to be rendered for each release in the changelog. -# See https://keats.github.io/tera/docs/#introduction -body = """ -{%- macro remote_url() -%} - https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }} -{%- endmacro -%} - -{% if version -%} - ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} -{% else -%} - ## [Unreleased] -{% endif -%} - -{% for group, commits in commits | group_by(attribute="group") %} - ### {{ group | striptags | trim | upper_first }} - {%- for commit in commits %} - - {{ commit.message | split(pat="\n") | first | upper_first | trim }}\ - {% if commit.remote.username %} by @{{ commit.remote.username }}{%- endif -%} - {% if commit.remote.pr_number %} in \ - [#{{ commit.remote.pr_number }}]({{ self::remote_url() }}/pull/{{ commit.remote.pr_number }}) \ - {%- endif -%} - {% endfor %} -{% endfor %} - -{%- if github.contributors | filter(attribute="is_first_time", value=true) | length != 0 %} - ## New Contributors -{%- endif -%} - -{% for contributor in github.contributors | filter(attribute="is_first_time", value=true) %} - * @{{ contributor.username }} made their first contribution - {%- if contributor.pr_number %} in \ - [#{{ contributor.pr_number }}]({{ self::remote_url() }}/pull/{{ contributor.pr_number }}) \ - {%- endif %} -{%- endfor %}\n - -""" -# A Tera template to be rendered as the changelog's footer. -# See https://keats.github.io/tera/docs/#introduction -footer = """ -{%- macro remote_url() -%} - https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }} -{%- endmacro -%} -""" -# Remove leading and trailing whitespaces from the changelog's body. -trim = true - -[git] -# Parse commits according to the conventional commits specification. -# See https://www.conventionalcommits.org -conventional_commits = true -# Exclude commits that do not match the conventional commits specification. -filter_unconventional = false -# An array of regex based parsers to modify commit messages prior to further processing. -commit_preprocessors = [ - # Remove issue numbers. - { pattern = '\((\w+\s)?#([0-9]+)\)', replace = "" }, -] -# An array of regex based parsers for extracting data from the commit message. -# Assigns commits to groups. -# Optionally sets the commit's scope and can decide to exclude commits from further processing. -commit_parsers = [ - { message = "^feat", group = "Features" }, - { message = "^fix", group = "Bug Fixes" }, - { message = "^doc", group = "Documentation" }, - { message = "^perf", group = "Performance" }, - { message = "^refactor", group = "Refactor" }, - { message = "^style", group = "Styling" }, - { message = "^test", group = "Testing" }, - { message = "^chore\\(release\\): prepare for", skip = true }, - { message = "^chore\\(deps.*\\)", skip = true }, - { message = "^chore\\(pr\\)", skip = true }, - { message = "^chore\\(pull\\)", skip = true }, - { message = "^chore|^ci", group = "Miscellaneous Tasks" }, - { body = ".*security", group = "Security" }, - { message = "^revert", group = "Revert" }, - { message = ".*", group = "Other" }, -] -# Exclude commits that are not matched by any commit parser. -filter_commits = false -# Order releases topologically instead of chronologically. -topo_order = false -# Order of commits in each group/release within the changelog. -# Allowed values: newest, oldest -sort_commits = "newest" diff --git a/.github/funding.yml b/.github/funding.yml deleted file mode 100644 index 5757a0a..0000000 --- a/.github/funding.yml +++ /dev/null @@ -1 +0,0 @@ -buy_me_a_coffee: devopvoid \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ff80b97..f82eaa3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,21 +3,19 @@ name: Build on: push: branches: - - main - paths: - - "**.cpp" - - "**.h" - - "**.java" - - "**/CMakeLists.txt" + - '**' + paths-ignore: + - '.github/ISSUE_TEMPLATE/*.yml' + - '.gitignore' + - 'CONTRIBUTING.md' + - 'LICENSE' + - 'NOTICE' + - 'README.md' pull_request: - branches: - - main - workflow_dispatch: env: - WEBRTC_CACHE_BRANCH: 7339 WEBRTC_CHECKOUT_FOLDER: ~/webrtc jobs: @@ -32,20 +30,19 @@ jobs: runs-on: ${{ matrix.platform.runs-on }} steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 + # https://github.com/actions/checkout/releases/latest - id: prepare name: Prepare build uses: ./.github/actions/prepare-windows - - id: maven-build - name: Maven build + - id: gradle-build + name: Gradle build uses: ./.github/actions/build with: java-version: ${{ matrix.java }} platform-name: ${{ matrix.platform.name }} - maven-username: ${{ secrets.MAVEN_USERNAME }} - maven-password: ${{ secrets.MAVEN_TOKEN }} build-linux: strategy: @@ -62,20 +59,19 @@ jobs: runs-on: ${{ matrix.platform.runs-on }} steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 + # https://github.com/actions/checkout/releases/latest - id: prepare name: Prepare build uses: ./.github/actions/prepare-linux - - id: maven-build - name: Maven build + - id: gradle-build + name: Gradle build uses: ./.github/actions/build with: java-version: ${{ matrix.java }} platform-name: ${{ matrix.platform.name }} - maven-username: ${{ secrets.MAVEN_USERNAME }} - maven-password: ${{ secrets.MAVEN_TOKEN }} build-macos: strategy: @@ -83,35 +79,23 @@ jobs: matrix: platform: - name: macos_x86-64 - runs-on: macos-14 + runs-on: macos-15-intel - name: macos_arm64 runs-on: macos-14 java: [17] runs-on: ${{ matrix.platform.runs-on }} steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 + # https://github.com/actions/checkout/releases/latest - id: prepare-build name: Prepare build uses: ./.github/actions/prepare-macos - - id: maven-build-arm64 - name: Maven build - Apple Silicon - if: matrix.platform.name == 'macos_arm64' + - id: gradle-build + name: Gradle build uses: ./.github/actions/build with: java-version: ${{ matrix.java }} platform-name: ${{ matrix.platform.name }} - maven-username: ${{ secrets.MAVEN_USERNAME }} - maven-password: ${{ secrets.MAVEN_TOKEN }} - - - id: maven-build-x86_64 - name: Maven build - Intel - if: matrix.platform.name == 'macos_x86-64' - uses: ./.github/actions/build-macos-x86_64 - with: - java-version: ${{ matrix.java }} - platform-name: ${{ matrix.platform.name }} - maven-username: ${{ secrets.MAVEN_USERNAME }} - maven-password: ${{ secrets.MAVEN_TOKEN }} diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml deleted file mode 100644 index 1521985..0000000 --- a/.github/workflows/pages.yml +++ /dev/null @@ -1,62 +0,0 @@ -name: Deploy Documentation to Pages - -on: - push: - branches: [main] - paths: - - 'docs/**' - - workflow_dispatch: - -permissions: - contents: read - pages: write - id-token: write - -concurrency: - group: pages - cancel-in-progress: false - -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v5 - - - name: Setup Node - uses: actions/setup-node@v5 - with: - node-version: 22 - cache: npm - cache-dependency-path: docs/package-lock.json - - - name: Setup Pages - uses: actions/configure-pages@v5 - - - name: Install dependencies - run: | - cd docs - npm ci - - - name: Build with VitePress - run: | - cd docs - npm run build - - - name: Upload artifact - uses: actions/upload-pages-artifact@v4 - with: - path: docs/.vitepress/dist - - deploy: - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - needs: build - runs-on: ubuntu-latest - name: Deploy - steps: - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v4 \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index fecbdbe..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,275 +0,0 @@ -name: Release - -on: - workflow_dispatch: - inputs: - developmentVersion: - description: "Default version to use for new local working copy." - required: true - default: "X.Y.Z-SNAPSHOT" - -env: - WEBRTC_CACHE_BRANCH: 7339 - WEBRTC_CHECKOUT_FOLDER: ~/webrtc - -jobs: - changelog: - name: Generate changelog - runs-on: ubuntu-latest - outputs: - release_body: ${{ steps.git-cliff.outputs.content }} - release_version: ${{ steps.git-cliff.outputs.version }} - - steps: - - name: Checkout - uses: actions/checkout@v5 - with: - fetch-depth: 0 - - - name: Git config - run: | - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - - - name: Generate changelog for the current build - uses: orhun/git-cliff-action@v4 - id: git-cliff - with: - config: .github/changelog/cliff-release.toml - args: -v -u --strip footer --bump --use-branch-tags - - - name: Update CHANGELOG.md - uses: orhun/git-cliff-action@v4 - with: - config: .github/changelog/cliff.toml - args: -v --bump --use-branch-tags - env: - OUTPUT: CHANGELOG.md - - - name: Commit CHANGELOG.md - run: | - git add CHANGELOG.md - git commit -m "chore(release): Update CHANGELOG.md for ${{ steps.git-cliff.outputs.version }}" - git push - - prepare-release: - name: Prepare release - needs: changelog - outputs: - release_body: ${{ needs.changelog.outputs.release_body }} - release_version: ${{ needs.changelog.outputs.release_version }} - strategy: - fail-fast: false - matrix: - platform: - - name: linux_x86-64 - runs-on: ubuntu-22.04 - runs-on: ${{ matrix.platform.runs-on }} - steps: - - name: Checkout code - uses: actions/checkout@v5 - with: - ref: main - - run: | - git config --global user.name "${{ github.actor }}" - git config --global user.email "${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com" - - - id: prepare - name: Prepare release build - uses: ./.github/actions/prepare-linux - - - name: Set up Java - uses: actions/setup-java@v5 - with: - java-version: '21' - distribution: 'temurin' - server-id: central - server-username: MAVEN_USERNAME - server-password: MAVEN_TOKEN - gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} - gpg-passphrase: MAVEN_GPG_PASSPHRASE - - - name: Update development version - uses: actions/checkout@v5 - with: - ref: main - env: - MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} - MAVEN_TOKEN: ${{ secrets.MAVEN_TOKEN }} - MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} - - run: | - mvn release:prepare -DskipTests -DpushChanges=false -DdevelopmentVersion=${{ github.event.inputs.developmentVersion }} - - # Get the release version from the release.properties file - RELEASE_VERSION=$(grep "project.rel.dev.kastle.webrtc\\\:webrtc-java=" release.properties | cut -d'=' -f2) - echo "Extracted release version from release.properties: $RELEASE_VERSION" - - # Update versions.ts file - echo "Updating versions.ts with release version: $RELEASE_VERSION and development version: ${{ github.event.inputs.developmentVersion }}" - sed -i "s/VERSION: '.*'/VERSION: '$RELEASE_VERSION'/g" docs/.vitepress/versions.ts - sed -i "s/VERSION_SNAPSHOT: '.*'/VERSION_SNAPSHOT: '${{ github.event.inputs.developmentVersion }}'/g" docs/.vitepress/versions.ts - - # Add the updated file to the existing commit - git add docs/.vitepress/versions.ts - git commit --amend --no-edit - - git push - git push --tags - - build-windows: - needs: prepare-release - outputs: - release_body: ${{ needs.prepare-release.outputs.release_body }} - release_version: ${{ needs.prepare-release.outputs.release_version }} - strategy: - fail-fast: false - matrix: - platform: - - name: windows_x86_64 - runs-on: windows-2022 - java: [17] - runs-on: ${{ matrix.platform.runs-on }} - steps: - - name: Checkout code - uses: actions/checkout@v5 - with: - fetch-tags: true - - - name: Get tag from current branch - id: tag-selector - shell: bash - run: | - git fetch -a - tag=$(git describe --tags `git rev-list --tags --max-count=1`) - echo "tag=$tag" >> "$GITHUB_OUTPUT" - git checkout $tag - - - id: prepare - name: Prepare release build - uses: ./.github/actions/prepare-windows - - - id: maven-build - name: Maven build - uses: ./.github/actions/release - with: - java-version: ${{ matrix.java }} - platform-name: ${{ matrix.platform.name }} - maven-username: ${{ secrets.MAVEN_USERNAME }} - maven-password: ${{ secrets.MAVEN_TOKEN }} - maven-gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} - maven-gpg-passphrase: ${{ secrets.MAVEN_GPG_PASSPHRASE }} - - build-linux: - needs: prepare-release - strategy: - fail-fast: false - matrix: - platform: - - name: linux_arm - runs-on: ubuntu-22.04 - - name: linux_arm64 - runs-on: ubuntu-22.04 - - name: linux_x86-64 - runs-on: ubuntu-22.04 - java: [17] - runs-on: ${{ matrix.platform.runs-on }} - steps: - - name: Checkout code - uses: actions/checkout@v5 - with: - fetch-tags: true - - - name: Get tag from current branch - id: tag-selector - run: | - git fetch -a - tag=$(git describe --tags `git rev-list --tags --max-count=1`) - echo "tag=$tag" >> "$GITHUB_OUTPUT" - git checkout $tag - - - id: prepare-build - name: Prepare release build - uses: ./.github/actions/prepare-linux - - - id: maven-build - name: Maven build - uses: ./.github/actions/release - with: - java-version: ${{ matrix.java }} - platform-name: ${{ matrix.platform.name }} - maven-username: ${{ secrets.MAVEN_USERNAME }} - maven-password: ${{ secrets.MAVEN_TOKEN }} - maven-gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} - maven-gpg-passphrase: ${{ secrets.MAVEN_GPG_PASSPHRASE }} - - build-macos: - needs: prepare-release - strategy: - fail-fast: false - matrix: - platform: - - name: macos_x86-64 - runs-on: macos-14 - - name: macos_arm64 - runs-on: macos-14 - java: [17] - runs-on: ${{ matrix.platform.runs-on }} - steps: - - name: Checkout code - uses: actions/checkout@v5 - with: - fetch-tags: true - - - name: Get tag from current branch - id: tag-selector - run: | - git fetch -a - tag=$(git describe --tags `git rev-list --tags --max-count=1`) - echo "tag=$tag" >> "$GITHUB_OUTPUT" - git checkout $tag - - - id: prepare-build - name: Prepare release build - uses: ./.github/actions/prepare-macos - - - id: maven-build-arm64 - name: Maven build - Apple Silicon - if: matrix.platform.name == 'macos_arm64' - uses: ./.github/actions/release - with: - java-version: ${{ matrix.java }} - platform-name: ${{ matrix.platform.name }} - maven-username: ${{ secrets.MAVEN_USERNAME }} - maven-password: ${{ secrets.MAVEN_TOKEN }} - maven-gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} - maven-gpg-passphrase: ${{ secrets.MAVEN_GPG_PASSPHRASE }} - - - id: maven-build-x86_64 - name: Maven build - Intel - if: matrix.platform.name == 'macos_x86-64' - uses: ./.github/actions/release-macos-x86_64 - with: - java-version: ${{ matrix.java }} - platform-name: ${{ matrix.platform.name }} - maven-username: ${{ secrets.MAVEN_USERNAME }} - maven-password: ${{ secrets.MAVEN_TOKEN }} - maven-gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} - maven-gpg-passphrase: ${{ secrets.MAVEN_GPG_PASSPHRASE }} - - publish-release: - name: Publish GitHub release - needs: [build-windows, build-linux, build-macos] - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v5 - - - name: Publish - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - version="${{ needs.build-windows.outputs.release_version }}" - body="${{ needs.build-windows.outputs.release_body }}" - - gh release create $version -d -t "Release $version" -n "$body" \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index f77e02a..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,447 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -## [0.14.0] - 2025-08-28 - -### Features -- Restrict ICE port ranges and control candidate gathering behavior by @devopvoid in [#202](https://github.com/devopvoid/webrtc-java/pull/202) -- Push or pull audio frames with a headless audio device module by @devopvoid in [#201](https://github.com/devopvoid/webrtc-java/pull/201) -- Add guide for configuring send-only and receive-only media by @devopvoid -- Add the platform classifier to the native library filename by @SnirDecartAI in [#194](https://github.com/devopvoid/webrtc-java/pull/194) -- Add VideoBufferConverter.convertToI420 by @SnirDecartAI in [#192](https://github.com/devopvoid/webrtc-java/pull/192) -- Add SyncClock for audio and video synchronization support by @devopvoid -- Add CustomVideoSource and related JNI bindings for video frame handling by @devopvoid -- Added a new web-based example by @devopvoid -- Custom audio source that can be provided to audio tracks by @devopvoid in [#188](https://github.com/devopvoid/webrtc-java/pull/188) - -### Bug Fixes -- RTCDtmfSenderTests timeouts by @devopvoid -- Update error handling to stop capturing on permanent errors #186 by @devopvoid -- Ensure JNIEnv is properly attached before deleting global reference 146 by @devopvoid -- Return a valid NtpTime from SyncClock::GetNtpTime by @SnirDecartAI in [#193](https://github.com/devopvoid/webrtc-java/pull/193) -- Release video frame after processing in WHEP example #191 by @devopvoid -- Made RTCRtpCodecCapability's int fields optional by @SnirDecartAI in [#190](https://github.com/devopvoid/webrtc-java/pull/190) - -### Documentation -- Add AudioRecorder and AudioPlayer documentation by @devopvoid -- Documentation for VideoBufferConverter by @devopvoid -- Documentation for MediaStreamTrack, VideoBufferConverter, and VideoCapture by @devopvoid -- Add Video Capture guide by @devopvoid -- Add Screen Capturer and Window Capturer guides by @devopvoid -- Add Power Management utility by @devopvoid -- Add Audio Converter guide by @devopvoid -- Add Voice Activity Detector guide by @devopvoid -- Reorganize media guides into categories by @devopvoid -- Add section on disabling audio processing with dummy audio layer by @devopvoid -- Add Custom Video Source guide and update documentation by @devopvoid -- Update example descriptions and add WebClientExample by @devopvoid -- Add Custom Audio Source guide by @devopvoid -- Update asset paths and add a privacy policy by @devopvoid in [#187](https://github.com/devopvoid/webrtc-java/pull/187) -- Add camera capture guide by @devopvoid -- Update CHANGELOG.md by @devopvoid - -### Miscellaneous Tasks -- Add custom video source and generator to the web example by @devopvoid - -### Other -- Update release workflow to use main branch by @devopvoid -- Update GitHub Actions workflows to use changelog generation by @devopvoid -- Update all GitHub Actions setup-java to v5 by @maxkratz in [#200](https://github.com/devopvoid/webrtc-java/pull/200) -- Prepare for next development iteration by @devopvoid - -## New Contributors -* @maxkratz made their first contribution in [#200](https://github.com/devopvoid/webrtc-java/pull/200) -* @SnirDecartAI made their first contribution in [#194](https://github.com/devopvoid/webrtc-java/pull/194) - -## [0.13.0] - 2025-07-25 - -### Features -- Add H.264 support and improve linking options for Apple platforms by @devopvoid -- Add RTCDtmfSender implementation for sending DTMF tones #115 by @devopvoid in [#183](https://github.com/devopvoid/webrtc-java/pull/183) -- Enable H.264 support for Linux and Windows builds #155 #168 #169 by @devopvoid - -### Bug Fixes -- Update references from master to main in build configuration and documentation by @devopvoid -- Enhance documentation for audio related topics by @devopvoid -- Validate COM initialization in audio device management #181 by @devopvoid -- MacOS screen capturing with iOSurface and platform thread management by @devopvoid - -### Documentation -- Update README with logo by @devopvoid -- Improve responsive design for the cover by @devopvoid -- Enhance coverpage and sidebar styles with new logo and theme colors by @devopvoid -- Update homepage and quickstart guide links in documentation by @devopvoid -- Comprehensive guide and examples by @devopvoid in [#182](https://github.com/devopvoid/webrtc-java/pull/182) - -### Miscellaneous Tasks -- Update readme to 0.12.0 and update changelog by @devopvoid - -### Other -- Prepare release v0.13.0 by @devopvoid -- Update release workflow to update versions.js in docs by @devopvoid -- Create CNAME by @devopvoid -- Prepare for next development iteration by @devopvoid - - -## [0.12.0] - 2025-07-18 - -### Features -- Add copy method for NativeI420Buffer and VideoFrame by @devopvoid -- Added the missing macOS camera capture functionality by @devopvoid in [#180](https://github.com/devopvoid/webrtc-java/pull/180) - -### Bug Fixes -- Add Maven release action for macOS platforms by @devopvoid - -### Refactor -- Updated native interface to m138 by @devopvoid in [#179](https://github.com/devopvoid/webrtc-java/pull/179) - -### Documentation -- Update badge links in README for build status and Maven Central by @devopvoid -- Update README for version 0.11.0 and clarify build notes by @devopvoid - -### Other -- Prepare release v0.12.0 by @devopvoid -- Fix release workflow to support matrix.platform.name by @devopvoid -- Update package installation commands and enhance sysroot configuration by @devopvoid in [#178](https://github.com/devopvoid/webrtc-java/pull/178) -- Prepare for next development iteration by @devopvoid - - -## [0.11.0] - 2025-07-02 - -### Bug Fixes -- Windows clang profile activation by @devopvoid - -### Refactor -- VideoTrackDesktopSource extends AdaptedVideoTrackSource by @devopvoid -- Rtc and cricket to webrtc namespace by @devopvoid - -### Other -- Prepare release v0.11.0 by @devopvoid -- Add project name to pom.xml by @devopvoid -- Update release workflow to include code checkout and linux arm support by @devopvoid -- Link with libc++ and libc++abi on Linux and Windows by @devopvoid in [#175](https://github.com/devopvoid/webrtc-java/pull/175) -- Do not build with clang-cl on main by @devopvoid -- Fix screen-share memory leak by @devopvoid in [#174](https://github.com/devopvoid/webrtc-java/pull/174) -- Revert "refactor: rtc and cricket to webrtc namespace" by @devopvoid -- Revert "build: updated webrtc version to m137 in GitHub workflows" by @devopvoid -- Updated webrtc version to m137 in GitHub workflows by @devopvoid -- Updated project to the stable WebRTC branch 6998 by @devopvoid in [#163](https://github.com/devopvoid/webrtc-java/pull/163) -- Build.yml pipewire activated by @devopvoid -- Update README.md by @devopvoid -- Prepare for next development iteration by @devopvoid - - -## [0.10.0] - 2025-03-18 - -### Bug Fixes -- Added missing libx libraries to be installed in linux release workflow by @devopvoid -- Added missing libx libraries to be installed in GH actions by @devopvoid -- Crashes caused by video frame conversion by @devopvoid -- Linux crashes caused by unlinked libraries by @devopvoid - -### Other -- Prepare release v0.10.0 by @devopvoid -- Update README.md by @devopvoid -- Prepare for next development iteration by @devopvoid - - -## [0.9.0] - 2025-01-02 - -### Other -- Prepare release v0.9.0 by @devopvoid -- Crash after java callback if exception occurred by @arosov in [#154](https://github.com/devopvoid/webrtc-java/pull/154) -- Workflow build and release fixes by @devopvoid in [#156](https://github.com/devopvoid/webrtc-java/pull/156) -- Removed gpg from action workflow by @devopvoid -- Fixed action workflow deployment by @devopvoid -- Update action.yml by @devopvoid -- Updated build badge in README.md by @devopvoid -- Linux pm rtc logging by @devopvoid -- Fixed build workflow by @devopvoid -- Fixed and improved GitHub build workflow by @devopvoid in [#152](https://github.com/devopvoid/webrtc-java/pull/152) -- Screen inhibition by @devopvoid in [#150](https://github.com/devopvoid/webrtc-java/pull/150) -- Fixed crash with jdk version > 17 by @devopvoid -- Revert version of cmake-maven-plugin for compatibility with older maven by @devopvoid -- Updated maven plugin versions. by @devopvoid -- Fixed NPE in MediaDevices when no audio device is connected. by @devopvoid -- Update README.md with Linux ARM architectures by @devopvoid -- Added Linux ARM architectures for cross compilation by @devopvoid -- Fixed Apple Silicon build by @devopvoid -- Update README.md macOS arm64 release by @devopvoid -- Updated CHANGELOG and README by @devopvoid -- Prepare for next development iteration by @devopvoid - -## New Contributors -* @arosov made their first contribution in [#154](https://github.com/devopvoid/webrtc-java/pull/154) - -## [0.8.0] - 2023-10-14 - -### Other -- Prepare release v0.8.0 by @devopvoid -- Updated action runners by @devopvoid -- Dropped old demo code. New demo will be in a new repository by @devopvoid -- Added setFocusSelectedSource to DesktopCapturer and capture with DesktopAndCursorComposer by @devopvoid -- Add a build support for mac/aarch64 by @stevebriskin in [#109](https://github.com/devopvoid/webrtc-java/pull/109) -- Merge remote-tracking branch 'origin/master' by @devopvoid -- Update README.md by @doctorpangloss in [#96](https://github.com/devopvoid/webrtc-java/pull/96) -- Initialized configs to be used with GraalVM by @devopvoid -- Set linux version to ubuntu-20.04 due to audio system tests by @devopvoid -- Link libm from sysroot to increase GLIBC (<= 2.18) compatibility #108 by @devopvoid -- Updated CHANGELOG and README by @devopvoid -- Added workflow_dispatch to the release workflow by @devopvoid -- Removed demo tasks from the release workflow by @devopvoid -- Prepare for next development iteration by @devopvoid - -## New Contributors -* @stevebriskin made their first contribution in [#109](https://github.com/devopvoid/webrtc-java/pull/109) -* @doctorpangloss made their first contribution in [#96](https://github.com/devopvoid/webrtc-java/pull/96) - -## [0.7.0] - 2022-11-14 - -### Bug Fixes -- Fix memory leak by @kalgecin in [#86](https://github.com/devopvoid/webrtc-java/pull/86) - -### Other -- Prepare release v0.7.0 by @devopvoid -- Fixed audio device names on mac #28 by @devopvoid -- Compile with backward compatibility for Java 8 by @devopvoid -- Terminate (end) VideoTrackDesktopSource if source cannot be selected by @devopvoid -- Fixed RTCRtpCodecParameters conversion when setting sender params by @devopvoid -- Fixed RTCRtpCodecParameters conversion by @devopvoid -- Notify the track to end on permanent error when capturing a desktop frame by @devopvoid -- Improved MediaStreamTrack "ended" and "muted" event observation by @devopvoid -- Added MediaStreamTrack "ended" and "muted" event observation by @devopvoid -- Removed Xcode version selection from the build workflow by @devopvoid -- VideoTrackDesktopSource crop black window borders by @devopvoid -- DesktopCaptureCallback convert DesktopFrame to I420 by @devopvoid -- Added setMaxFrameSize to VideoDesktopSource by @devopvoid -- Enable set min,max bitrate and max framerate in RTCRtpSender by @devopvoid -- Fixed crashes caused by DesktopCaptureCallback by @devopvoid -- MacOS build with Xcode 11.7 by @devopvoid -- Use new RemoveTrackOrError API call in RTCPeerConnection to remove a sender by @devopvoid -- Removed deprecated Windows wstring_convert calls by @devopvoid -- Build demo code with Maven 'demo' profile by @devopvoid -- Fixed RTCDataChannelTests by @devopvoid -- Fixed JavaEnums returning JavaLocalRef by @devopvoid -- Fixed JavaFactories returning jobjectArray by @devopvoid -- Fixed JavaLocalRefs for enums and factories by @devopvoid -- CI build with windows-2019 by @devopvoid -- Set maximum width and height for captured screen frames by @devopvoid -- Fixed null pointer handling with RtpSender by @devopvoid -- Added setFocusSelectedSource to VideoTrackDesktopSource by @devopvoid -- Compile with CXX_STANDARD 17 by @devopvoid -- Minor option changes for DesktopCapturer by @devopvoid -- Bump cmake-maven-plugin version to 3.22.1-b1 by @devopvoid -- Fixed memory leak in AudioTransportSink by @devopvoid -- Updated RTC_LOG macros by @devopvoid -- Removed deprecated code by @devopvoid -- Bump native branch to 4844 by @devopvoid -- Removed demos since AppRTC services have been turned down by @devopvoid -- Fixed setting codec preferences #57 by @devopvoid -- Removed setDesktopCapturer call on VideoDesktopSource by @devopvoid -- Fixed desktop capturing by @devopvoid -- Updated CHANGELOG and README by @devopvoid -- Prepare for next development iteration by @devopvoid - -## New Contributors -* @kalgecin made their first contribution in [#86](https://github.com/devopvoid/webrtc-java/pull/86) - -## [0.6.0] - 2022-01-17 - -### Other -- Prepare release v0.6.0 by @devopvoid -- Fixed camera device selection for a video track on Unix systems #30 by @devopvoid -- Get default audio devices by @devopvoid in [#50](https://github.com/devopvoid/webrtc-java/pull/50) -- Lazy-load audio/video managers #44 by @devopvoid -- Fixed loading classes from native threads with detached class-loaders #49 by @devopvoid -- Moved to WebRTC branch 4692 (M97) by @devopvoid -- Updated workflow actions to WebRTC branch 4664 (M96) by @devopvoid -- Moved to WebRTC branch 4664 (M96) by @devopvoid -- Fixed AudioProcessing native ProcessReverseStream function call #46 by @devopvoid -- Updated CHANGELOG and README by @devopvoid -- Prepare for next development iteration by @devopvoid - - -## [0.5.0] - 2021-11-25 - -### Other -- Prepare release v0.5.0 by @devopvoid -- Use new api calls which support RTCError by @devopvoid -- Fixed AudioTransportSource.cpp buffer passing by @devopvoid -- Updated RTCStats.cpp to Java mapping by @devopvoid -- Got rid of warnings in the audio section by @devopvoid -- Fixed NPE on RTCPeerConnection.getConnectionState when peer-connection has been closed #35 by @devopvoid -- AudioConverter implementation for remixing and resampling by @devopvoid -- Minor audio procession improvements by @devopvoid -- Fixed basic channel up-mixing in AudioProcessing by @devopvoid -- Improved audio processing by basic channel up-mixing to avoid additional audio converter by @devopvoid -- Fixed AudioTransportSource buffer reading by @devopvoid -- Fixed NPE in AudioProcessingConfig when no NS level was set by @devopvoid -- Fixed CoInitialize has not been called #43 by @devopvoid -- Updated CHANGELOG and README by @devopvoid -- Prepare for next development iteration by @devopvoid - - -## [0.4.0] - 2021-11-21 - -### Other -- Prepare release v0.4.0 by @devopvoid -- Add settings-path for JDK setup to the release workflow by @devopvoid -- Split AudioProcessingConfig into individual config classes. Added get/set of stream-delay to AudioProcessing. by @devopvoid -- Add option to provide AudioProcessing to the PeerConnectionFactory by @devopvoid -- AudioResampler fixes for more than one channel by @devopvoid -- AudioResampler utility class which can be used for sampling rate conversion by @devopvoid -- AudioProcessing to use only 16 Bit audio samples by @devopvoid -- AudioPlayer and AudioRecorder utility classes which utilize the AudioDeviceModule by @devopvoid -- Introduced AudioSink and AudioSource interfaces which can be passed to the AudioDeviceModule by @devopvoid -- Audio/VideoSource renamed to Audio/VideoTrackSource by @devopvoid -- Fixed temporary MTA<>STA threading issue #39 by @devopvoid -- Static linking libgcc and libstdc++ #27 by @devopvoid -- Fixed action workflow cache saving and loading by @devopvoid -- AudioProcessing implementation by @devopvoid -- Native JavaObject field setters by @devopvoid -- Init version of Java implementation of AudioProcessing by @devopvoid -- Workflow 'apt-get update' for linux action by @devopvoid -- Added more audio processing options by @devopvoid -- Moved to WebRTC branch 4638 (M95) by @devopvoid -- Added stop/start methods for playout/recording by @devopvoid -- Updated CHANGELOG and README by @devopvoid -- Updated CHANGELOG and README by @devopvoid -- Prepare for next development iteration by @devopvoid - - -## [0.3.0] - 2021-08-19 - -### Other -- Prepare release v0.3.0 by @devopvoid -- Fixed local video is sometimes empty #9 by @devopvoid -- Fixed WebRTC cmake build by @devopvoid -- Fixed NPE in JNI_PeerConnectionFactory by @devopvoid -- Switch to a more stable branch (4515) by @devopvoid -- Update pom.xml by @devopvoid -- Update CMakeLists.txt by @devopvoid -- Update pom.xml by @devopvoid -- Merge remote-tracking branch 'origin/master' by @devopvoid -- Update README.md by @devopvoid -- Audio/video device (Windows) handling consistent with the internal API by @devopvoid -- Audio device retrieval with the AudioDeviceModule by @devopvoid -- Removed Azure Pipelines by @devopvoid -- Merge pull request #20 from rmberne/dummy-audio-for-testing by @devopvoid in [#20](https://github.com/devopvoid/webrtc-java/pull/20) -- Use dummy audio in the unit test by @rmberne -- Add possibility to use dummy audio for testing purposes by @rmberne -- Fixed NativeI420Buffer allocate by @devopvoid -- Add VideoCapture to capture frames without a running track by @devopvoid -- Removed usage of webrtc::VideoType::kARGB1555 by @devopvoid -- Updated pipelines by @devopvoid -- Removed usage of webrtc::VideoType::kNV12 by @devopvoid -- Updated WebRTC branch to 4472 (M91) and updated dependency versions by @devopvoid -- Updated Sonatype provision URL by @devopvoid -- Fixed desktop capture by @devopvoid -- Bind transceiver direction to the configuration by @devopvoid -- Fixed demo audio/video config settings by @devopvoid -- Revert "Create codeql-analysis.yml" by @devopvoid -- Create codeql-analysis.yml by @devopvoid -- Updated GitHub Actions workflows by @devopvoid -- Update README.md by @devopvoid -- Merge remote-tracking branch 'origin/master' by @devopvoid -- Update README.md by @devopvoid -- Fixed possible arithmetic overflow by @devopvoid -- Linux M88 patch. Updated pipelines. by @devopvoid -- Bump WebRTC branch to 4324 (M88) by @devopvoid -- Merge pull request #6 from averyzhong/master by @devopvoid in [#6](https://github.com/devopvoid/webrtc-java/pull/6) -- Update AVFVideoDeviceManager.cpp by @averyzhong -- Change GitHub Actions env names for Maven credentials by @devopvoid -- Fixed MF init scope by @devopvoid -- Fixed linux build dependencies in CI builds by @devopvoid -- Fixed macOS CoreAudioDeviceManager by @devopvoid -- Advance WebRTC branch to 4044 (m81) by @devopvoid -- MediaDevice change listener implementation by @devopvoid -- Refactored JNI helper classes by @devopvoid -- Show settings link in the start view by @devopvoid -- Add Maven Central badge to README by @devopvoid -- Reference javafx demo app name to 'webrtc-javafx-demo-(platform)' by @devopvoid -- Prepare for next development iteration by @devopvoid - -## New Contributors -* @rmberne made their first contribution -* @averyzhong made their first contribution - -## [0.2.0] - 2020-02-25 - -### Other -- Prepare release v0.2.0 by @devopvoid -- Added CHANGELOG by @devopvoid -- Update README by @devopvoid -- Cleanup Azure build pipeline by @devopvoid -- GitHub Actions CI/CD configurations by @devopvoid -- Merge branch 'master' of github.com:devopvoid/webrtc-java by @devopvoid -- Cleanup GitHub Actions workflow by @devopvoid -- Provide Azure Pipelines CI/CD configurations by @devopvoid -- Switched to maven-release-plugin by @devopvoid -- Improved platform classifier handling by @devopvoid -- Improved native CMake builds by @devopvoid -- Update maven build procedure by @devopvoid -- Update maven build procedure by @devopvoid -- Update README.md by @devopvoid -- Maven CI credentials by @devopvoid -- JavaFX demo code cleanup by @devopvoid -- Refactor bloated project structure by @devopvoid -- Java module fixes by @devopvoid -- Updated JavaFX version by @devopvoid -- Patch DEPS to reduce time running gclient by @devopvoid -- Update issue templates by @devopvoid -- RTP header extension refactoring by @devopvoid -- Fetch WebRTC with no history by @devopvoid -- Added Windows to CI builds by @devopvoid -- Refactored cmake builds for WebRTC by @devopvoid -- Linux and macOS CI builds by @devopvoid -- Removed travis config due to GitHub Actions by @devopvoid -- Create maven.yml by @devopvoid -- Fixed travis install-build-deps.sh URL by @devopvoid -- Travis config before_install by @devopvoid -- Travis config by @devopvoid -- Device and capabilities retrieval by @devopvoid -- ICE candidate error api implementation by @devopvoid -- Merge remote-tracking branch 'origin/master' by @devopvoid -- Update README.md by @devopvoid -- ICE candidate removal by @devopvoid -- Updated WebRTC license URL by @devopvoid -- AppRTC demo integration by @devopvoid -- Fixed fork crash when test is finished by @devopvoid -- Removed debug output and updated JUnit version to 5.6.0 by @devopvoid -- Fixed module tests by @devopvoid -- Fixed JavaFX maven-shade-plugin main class by @devopvoid -- Signaling room JavaFX api update by @devopvoid -- AppRTC signaling implementation by @devopvoid -- Native peer connection demo signaling client by @devopvoid -- Signaling room api by @devopvoid -- Change default demo logging by @devopvoid -- Switch to WebRTC branch M80/3987 by @devopvoid -- Update README.md by @devopvoid -- Added module-infos and changed JSON api dependencies by @devopvoid -- Add dynamic libraries to .gitignore by @devopvoid -- Removed unnecessary assert by @devopvoid -- Fixed Unix builds by @devopvoid -- Update README.md by @devopvoid -- Update README.md by @devopvoid -- Mac visibility compiler flags by @devopvoid -- Removed unnecessary includes -- Fixed and improved CMake builds by @devopvoid -- Updated JUnit version to 5.5.2 by @devopvoid -- Improved test cases by @devopvoid -- Fixed non-Windows build -- Prepare for next development iteration - - -## [0.1.0] - 2019-12-22 - -### Other -- Prepare release webrtc-java-0.1.0 -- Minor changes to the NOTICE and parent POM -- Initial commit by @devopvoid - -## New Contributors -* @ made their first contribution -* @devopvoid made their first contribution - - diff --git a/gradle.properties b/gradle.properties index b70178f..beb72cc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1 @@ -webrtc.branch=branch-heads/7339 version=1.0.0 \ No newline at end of file diff --git a/webrtc-jni/build.gradle.kts b/webrtc-jni/build.gradle.kts index 8abc883..cd922cd 100644 --- a/webrtc-jni/build.gradle.kts +++ b/webrtc-jni/build.gradle.kts @@ -68,7 +68,7 @@ val configureNative by tasks.registering(Exec::class) { args("-DWEBRTC_TOOLCHAIN_FILE=${toolchainFile.absolutePath}") } - val webrtcBranch = rootProject.property("webrtc.branch") as String? ?: "master" + val webrtcBranch = project.property("webrtc.branch") as String? ?: "master" logger.lifecycle("Using WebRTC Branch: $webrtcBranch") args("-DWEBRTC_BRANCH=$webrtcBranch") diff --git a/webrtc-jni/gradle.properties b/webrtc-jni/gradle.properties new file mode 100644 index 0000000..3d916ba --- /dev/null +++ b/webrtc-jni/gradle.properties @@ -0,0 +1 @@ +webrtc.branch=branch-heads/7339 \ No newline at end of file From 082cc8e74c47b235666d6ec87cb298a41a561a2f Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Thu, 25 Dec 2025 14:42:27 -0800 Subject: [PATCH 44/81] Supply java distribution Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/build/action.yml | 1 + .gitignore | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index 3960ab2..b71388c 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -26,6 +26,7 @@ runs: - uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # https://github.com/actions/setup-java/releases/latest with: + distribution: 'temurin' java-version: ${{ inputs.java-version }} - uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 diff --git a/.gitignore b/.gitignore index 79bc955..dd62756 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ # Gradle .gradle **/build/ +!.github/actions/build/ !src/**/build/ gradle-app.setting !gradle-wrapper.jar From e7a7dc3e4a2a81eae4a2fb97602c3a21b4d34d53 Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Thu, 25 Dec 2025 15:28:43 -0800 Subject: [PATCH 45/81] Log toolchain Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- webrtc-jni/build.gradle.kts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/webrtc-jni/build.gradle.kts b/webrtc-jni/build.gradle.kts index cd922cd..e697087 100644 --- a/webrtc-jni/build.gradle.kts +++ b/webrtc-jni/build.gradle.kts @@ -65,7 +65,10 @@ val configureNative by tasks.registering(Exec::class) { args("-DCMAKE_BUILD_TYPE=Release") if (toolchainFile.exists()) { + logger.lifecycle("Using Toolchain file: ${toolchainFile.absolutePath}") args("-DWEBRTC_TOOLCHAIN_FILE=${toolchainFile.absolutePath}") + } else { + logger.warn("Toolchain file not found for platform $targetPlatform: ${toolchainFile.absolutePath}") } val webrtcBranch = project.property("webrtc.branch") as String? ?: "master" From ddc2f5e43f9b182b16bd4513128a3a086dac221d Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Thu, 25 Dec 2025 15:39:39 -0800 Subject: [PATCH 46/81] Pass correct toolchain names Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/workflows/build.yml | 12 ++++++------ webrtc-jni/build.gradle.kts | 4 +--- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f82eaa3..8e7da3d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,7 +24,7 @@ jobs: fail-fast: false matrix: platform: - - name: windows_x86_64 + - name: windows-x86_64 runs-on: windows-2022 java: [17] runs-on: ${{ matrix.platform.runs-on }} @@ -49,11 +49,11 @@ jobs: fail-fast: false matrix: platform: - - name: linux_arm + - name: linux-aarch32 runs-on: ubuntu-22.04 - - name: linux_arm64 + - name: linux-aarch64 runs-on: ubuntu-22.04 - - name: linux_x86-64 + - name: linux-x86_64 runs-on: ubuntu-22.04 java: [17] runs-on: ${{ matrix.platform.runs-on }} @@ -78,9 +78,9 @@ jobs: fail-fast: false matrix: platform: - - name: macos_x86-64 + - name: macos-x86_64 runs-on: macos-15-intel - - name: macos_arm64 + - name: macos-aarch64 runs-on: macos-14 java: [17] runs-on: ${{ matrix.platform.runs-on }} diff --git a/webrtc-jni/build.gradle.kts b/webrtc-jni/build.gradle.kts index e697087..40b3165 100644 --- a/webrtc-jni/build.gradle.kts +++ b/webrtc-jni/build.gradle.kts @@ -34,8 +34,6 @@ if (targetPlatform == null) { targetPlatform = "$osFamily-$osArch" } -val platformClassifier = targetPlatform?.replace("_", "-") - logger.lifecycle("Configuring webrtc-jni for Platform: $targetPlatform") val toolchainFile = file("src/main/cpp/toolchain").resolve( @@ -121,7 +119,7 @@ tasks.named("processResources") { tasks.named("jar") { archiveBaseName.set("webrtc-java") - archiveClassifier.set(platformClassifier) + archiveClassifier.set(targetPlatform) } tasks.withType { enabled = false } \ No newline at end of file From 1079023487ce7ac40b1888d3fd57d0e3968d4ca6 Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Thu, 25 Dec 2025 15:50:43 -0800 Subject: [PATCH 47/81] Correct prepare-linux action Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/prepare-linux/action.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/actions/prepare-linux/action.yml b/.github/actions/prepare-linux/action.yml index 3d8c223..85111ac 100644 --- a/.github/actions/prepare-linux/action.yml +++ b/.github/actions/prepare-linux/action.yml @@ -41,16 +41,16 @@ runs: sudo tar -xvf clang-llvmorg-20-init-9764-gb81d8e90-72.tar.xz -C /opt/clang shell: bash - - name: Install required packages for x86-64 - if: matrix.platform.name == 'linux_x86-64' + - name: Install required packages for linux-x86_64 + if: matrix.platform.name == 'linux-x86_64' run: | sudo mkdir /opt/sysroot python3 webrtc-jni/src/main/cpp/dependencies/webrtc/linux/sysroot/install-sysroot.py --arch=amd64 sudo mv webrtc-jni/src/main/cpp/dependencies/webrtc/linux/debian* /opt/sysroot/ shell: bash - - name: Install required packages for arm - if: matrix.platform.name == 'linux_arm' + - name: Install required packages for linux-aarch32 + if: matrix.platform.name == 'linux-aarch32' run: | sudo apt install -y gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf @@ -59,8 +59,8 @@ runs: sudo mv webrtc-jni/src/main/cpp/dependencies/webrtc/linux/debian* /opt/sysroot/ shell: bash - - name: Install required packages for arm64 - if: matrix.platform.name == 'linux_arm64' + - name: Install required packages for linux-aarch64 + if: matrix.platform.name == 'linux-aarch64' run: | sudo apt install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu From 021ff1a8e033063b67508ee0a4f5188fa972982c Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Thu, 25 Dec 2025 16:34:18 -0800 Subject: [PATCH 48/81] Use arm runners Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8e7da3d..c88f1b2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -50,9 +50,9 @@ jobs: matrix: platform: - name: linux-aarch32 - runs-on: ubuntu-22.04 + runs-on: ubuntu-22.04-arm - name: linux-aarch64 - runs-on: ubuntu-22.04 + runs-on: ubuntu-22.04-arm - name: linux-x86_64 runs-on: ubuntu-22.04 java: [17] From ff2d0b2092affad443899a52ed2a62d6ccda5e09 Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Thu, 25 Dec 2025 17:09:51 -0800 Subject: [PATCH 49/81] Use native clang Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/build/action.yml | 4 ++-- .github/actions/prepare-linux/action.yml | 8 +------- .github/workflows/build.yml | 4 ---- 3 files changed, 3 insertions(+), 13 deletions(-) diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index b71388c..f4ae7e1 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -1,4 +1,4 @@ -name: "Maven Build" +name: "Gradle Build" description: "Build the platform dependent Java library" @@ -19,7 +19,7 @@ runs: uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # https://github.com/actions/cache/releases/latest with: - path: ${{ env.WEBRTC_CHECKOUT_FOLDER }}/build + path: ${{ github.workspace }}/webrtc-jni/src/main/cpp/dependencies/webrtc/webrtc-source/build key: webrtc-${{ hashFiles('webrtc-jni/gradle.properties') }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt') }} restore-keys: webrtc-${{ hashFiles('webrtc-jni/gradle.properties') }}-${{ inputs.platform-name }}- diff --git a/.github/actions/prepare-linux/action.yml b/.github/actions/prepare-linux/action.yml index 85111ac..029d4a0 100644 --- a/.github/actions/prepare-linux/action.yml +++ b/.github/actions/prepare-linux/action.yml @@ -32,13 +32,7 @@ runs: run: | sudo apt update sudo apt install -y binutils cmake git locales lsb-release ninja-build pkg-config python3 python3-setuptools rsync unzip wget xz-utils - - # Chromium Clang to be used with the clang toolchain file - #curl -s https://raw.githubusercontent.com/chromium/chromium/main/tools/clang/scripts/update.py | python3 - --output-dir=/opt/clang - # Use a more stable version of Clang - sudo mkdir -p /opt/clang - wget https://commondatastorage.googleapis.com/chromium-browser-clang/Linux_x64/clang-llvmorg-20-init-9764-gb81d8e90-72.tar.xz - sudo tar -xvf clang-llvmorg-20-init-9764-gb81d8e90-72.tar.xz -C /opt/clang + sudo apt install -y clang lld llvm shell: bash - name: Install required packages for linux-x86_64 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c88f1b2..8429ec9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,13 +11,9 @@ on: - 'LICENSE' - 'NOTICE' - 'README.md' - pull_request: workflow_dispatch: -env: - WEBRTC_CHECKOUT_FOLDER: ~/webrtc - jobs: build-windows: strategy: From d61e18464b16683dc9c3fed8d23efdb7cc72fbcc Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Thu, 25 Dec 2025 17:26:11 -0800 Subject: [PATCH 50/81] Put webrtc back in home folder because windows can't have long filenames... Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/build/action.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index f4ae7e1..d553704 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -19,7 +19,7 @@ runs: uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # https://github.com/actions/cache/releases/latest with: - path: ${{ github.workspace }}/webrtc-jni/src/main/cpp/dependencies/webrtc/webrtc-source/build + path: ${{ env.HOME }}/webrtc/build key: webrtc-${{ hashFiles('webrtc-jni/gradle.properties') }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt') }} restore-keys: webrtc-${{ hashFiles('webrtc-jni/gradle.properties') }}-${{ inputs.platform-name }}- @@ -34,6 +34,7 @@ runs: - name: Build env: + WEBRTC_CHECKOUT_FOLDER: ${{ env.HOME }}/webrtc WEBRTC_PLATFORM: ${{ inputs.platform-name }} run: ./gradlew build shell: bash From bb0c8889fbac6e847ac9102cd0f2baf669e737db Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Thu, 25 Dec 2025 17:33:48 -0800 Subject: [PATCH 51/81] Shorter path Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/build/action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index d553704..4fa0172 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -19,7 +19,7 @@ runs: uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # https://github.com/actions/cache/releases/latest with: - path: ${{ env.HOME }}/webrtc/build + path: ${{ github.workspace }}/wrtc/build key: webrtc-${{ hashFiles('webrtc-jni/gradle.properties') }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt') }} restore-keys: webrtc-${{ hashFiles('webrtc-jni/gradle.properties') }}-${{ inputs.platform-name }}- @@ -34,7 +34,7 @@ runs: - name: Build env: - WEBRTC_CHECKOUT_FOLDER: ${{ env.HOME }}/webrtc + WEBRTC_CHECKOUT_FOLDER: ${{ github.workspace }}/wrtc WEBRTC_PLATFORM: ${{ inputs.platform-name }} run: ./gradlew build shell: bash From 645ae2f369fdd2617ca9a3df0d7a6db1b7b1fbae Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Thu, 25 Dec 2025 18:15:34 -0800 Subject: [PATCH 52/81] Skip tests on arm platforms Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/build/action.yml | 1 + .github/actions/prepare-linux/action.yml | 8 +++++++- .github/workflows/build.yml | 4 ++-- webrtc/build.gradle.kts | 6 ++++++ 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index 4fa0172..958a59b 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -36,6 +36,7 @@ runs: env: WEBRTC_CHECKOUT_FOLDER: ${{ github.workspace }}/wrtc WEBRTC_PLATFORM: ${{ inputs.platform-name }} + SKIP_TESTS: ${{ inputs.platform-name == 'linux-aarch32' || inputs.platform-name == 'linux-aarch64' }} run: ./gradlew build shell: bash diff --git a/.github/actions/prepare-linux/action.yml b/.github/actions/prepare-linux/action.yml index 029d4a0..85111ac 100644 --- a/.github/actions/prepare-linux/action.yml +++ b/.github/actions/prepare-linux/action.yml @@ -32,7 +32,13 @@ runs: run: | sudo apt update sudo apt install -y binutils cmake git locales lsb-release ninja-build pkg-config python3 python3-setuptools rsync unzip wget xz-utils - sudo apt install -y clang lld llvm + + # Chromium Clang to be used with the clang toolchain file + #curl -s https://raw.githubusercontent.com/chromium/chromium/main/tools/clang/scripts/update.py | python3 - --output-dir=/opt/clang + # Use a more stable version of Clang + sudo mkdir -p /opt/clang + wget https://commondatastorage.googleapis.com/chromium-browser-clang/Linux_x64/clang-llvmorg-20-init-9764-gb81d8e90-72.tar.xz + sudo tar -xvf clang-llvmorg-20-init-9764-gb81d8e90-72.tar.xz -C /opt/clang shell: bash - name: Install required packages for linux-x86_64 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8429ec9..d15f3d2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -46,9 +46,9 @@ jobs: matrix: platform: - name: linux-aarch32 - runs-on: ubuntu-22.04-arm + runs-on: ubuntu-22.04 - name: linux-aarch64 - runs-on: ubuntu-22.04-arm + runs-on: ubuntu-22.04 - name: linux-x86_64 runs-on: ubuntu-22.04 java: [17] diff --git a/webrtc/build.gradle.kts b/webrtc/build.gradle.kts index d499ae8..7bb9849 100644 --- a/webrtc/build.gradle.kts +++ b/webrtc/build.gradle.kts @@ -27,6 +27,12 @@ tasks.named("test") { } } +if (System.getenv("SKIP_TESTS") == "true") { + tasks.named("test") { + enabled = false + } +} + publishing { publications { create("maven") { From e7742c8ea14b1293444cb338991b7caa079e1c7c Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Thu, 25 Dec 2025 19:36:46 -0800 Subject: [PATCH 53/81] Fix windows compile and use rosetta for macos intel build Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/build/action.yml | 13 ++++++-- .github/workflows/build.yml | 2 +- webrtc-jni/build.gradle.kts | 32 ++++++++++++++----- .../jni-voithos/include/jni/windows/jni_md.h | 5 --- 4 files changed, 35 insertions(+), 17 deletions(-) diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index 958a59b..5a86a74 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -15,11 +15,18 @@ inputs: runs: using: "composite" steps: + - name: Create webrtc folder in home and save absolute path + id: set-webrtc-path + run: | + mkdir -p $HOME/webrtc + echo "WEBRTC_PATH=$HOME/webrtc" >> $GITHUB_ENV + shell: bash + - name: Set up WebRTC cache uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # https://github.com/actions/cache/releases/latest with: - path: ${{ github.workspace }}/wrtc/build + path: ${{ steps.set-webrtc-path.outputs.WEBRTC_PATH }}/build key: webrtc-${{ hashFiles('webrtc-jni/gradle.properties') }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt') }} restore-keys: webrtc-${{ hashFiles('webrtc-jni/gradle.properties') }}-${{ inputs.platform-name }}- @@ -34,9 +41,9 @@ runs: - name: Build env: - WEBRTC_CHECKOUT_FOLDER: ${{ github.workspace }}/wrtc + WEBRTC_CHECKOUT_FOLDER: ${{ steps.set-webrtc-path.outputs.WEBRTC_PATH }} WEBRTC_PLATFORM: ${{ inputs.platform-name }} - SKIP_TESTS: ${{ inputs.platform-name == 'linux-aarch32' || inputs.platform-name == 'linux-aarch64' }} + SKIP_TESTS: ${{ inputs.platform-name == 'linux-aarch32' || inputs.platform-name == 'linux-aarch64' || inputs.platform-name == 'macos-x86_64' }} run: ./gradlew build shell: bash diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d15f3d2..ee1e5a1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -75,7 +75,7 @@ jobs: matrix: platform: - name: macos-x86_64 - runs-on: macos-15-intel + runs-on: macos-14 - name: macos-aarch64 runs-on: macos-14 java: [17] diff --git a/webrtc-jni/build.gradle.kts b/webrtc-jni/build.gradle.kts index 40b3165..dd0c203 100644 --- a/webrtc-jni/build.gradle.kts +++ b/webrtc-jni/build.gradle.kts @@ -14,9 +14,10 @@ val currentOs = OperatingSystem.current() var targetPlatform = System.getenv("WEBRTC_PLATFORM") as? String -if (targetPlatform == null) { - val rawArch = System.getProperty("os.arch").lowercase().trim() +val hostArch = System.getProperty("os.arch").lowercase().trim() +val isHostArm = hostArch == "aarch64" || hostArch == "arm64" +if (targetPlatform == null) { val osFamily = when { currentOs.isLinux -> "linux" currentOs.isMacOsX -> "macos" @@ -25,16 +26,21 @@ if (targetPlatform == null) { } val osArch = when { - rawArch == "amd64" || rawArch == "x86_64" || rawArch == "x86-64" -> "x86_64" - rawArch == "aarch64" || rawArch == "arm64" -> "aarch64" - rawArch.startsWith("arm") -> "aarch32" - else -> error("Unsupported Architecture: $rawArch") + hostArch == "amd64" || hostArch == "x86_64" || hostArch == "x86-64" -> "x86_64" + isHostArm -> "aarch64" + hostArch.startsWith("arm") -> "aarch32" + else -> error("Unsupported Architecture: $hostArch") } targetPlatform = "$osFamily-$osArch" } +val useRosetta = currentOs.isMacOsX && isHostArm && targetPlatform == "macos-x86_64" + logger.lifecycle("Configuring webrtc-jni for Platform: $targetPlatform") +if (useRosetta) { + logger.lifecycle("Building for x86_64 on ARM host -> Using 'arch -x86_64'") +} val toolchainFile = file("src/main/cpp/toolchain").resolve( when { @@ -58,7 +64,12 @@ val configureNative by tasks.registering(Exec::class) { cmakeBuildDir.get().asFile.mkdirs() } - commandLine("cmake") + if (useRosetta) { + commandLine("arch", "-x86_64", "cmake") + } else { + commandLine("cmake") + } + args("-S", ".", "-B", cmakeBuildDir.get().asFile.absolutePath) args("-DCMAKE_BUILD_TYPE=Release") @@ -81,7 +92,12 @@ val buildNative by tasks.registering(Exec::class) { group = "build" dependsOn(configureNative) - commandLine("cmake") + if (useRosetta) { + commandLine("arch", "-x86_64", "cmake") + } else { + commandLine("cmake") + } + args("--build", cmakeBuildDir.get().asFile.absolutePath) args("--config", "Release") diff --git a/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/jni/windows/jni_md.h b/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/jni/windows/jni_md.h index b94589b..3808001 100644 --- a/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/jni/windows/jni_md.h +++ b/webrtc-jni/src/main/cpp/dependencies/jni-voithos/include/jni/windows/jni_md.h @@ -30,11 +30,6 @@ #define JNIIMPORT __declspec(dllimport) #define JNICALL __stdcall -#ifndef __int64 -#include -#define __int64 int64_t -#endif - typedef long jint; typedef __int64 jlong; typedef signed char jbyte; From 38ac2c5b96121696181415b5b7e0cfe0b7d639c7 Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Thu, 25 Dec 2025 19:48:13 -0800 Subject: [PATCH 54/81] Hopefully fix env Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/build/action.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index 5a86a74..68fd025 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -15,18 +15,17 @@ inputs: runs: using: "composite" steps: - - name: Create webrtc folder in home and save absolute path - id: set-webrtc-path + - name: Create WebRTC checkout folder run: | mkdir -p $HOME/webrtc - echo "WEBRTC_PATH=$HOME/webrtc" >> $GITHUB_ENV + echo "WEBRTC_CHECKOUT_FOLDER=$HOME/webrtc" >> $GITHUB_ENV shell: bash - name: Set up WebRTC cache uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # https://github.com/actions/cache/releases/latest with: - path: ${{ steps.set-webrtc-path.outputs.WEBRTC_PATH }}/build + path: ${{ env.WEBRTC_CHECKOUT_FOLDER }}/build key: webrtc-${{ hashFiles('webrtc-jni/gradle.properties') }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt') }} restore-keys: webrtc-${{ hashFiles('webrtc-jni/gradle.properties') }}-${{ inputs.platform-name }}- @@ -41,7 +40,6 @@ runs: - name: Build env: - WEBRTC_CHECKOUT_FOLDER: ${{ steps.set-webrtc-path.outputs.WEBRTC_PATH }} WEBRTC_PLATFORM: ${{ inputs.platform-name }} SKIP_TESTS: ${{ inputs.platform-name == 'linux-aarch32' || inputs.platform-name == 'linux-aarch64' || inputs.platform-name == 'macos-x86_64' }} run: ./gradlew build From 3e0e26bae22dba165966abd8d8838a4e6877d17e Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Thu, 25 Dec 2025 19:59:11 -0800 Subject: [PATCH 55/81] Don't use arch for macos compile Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/build/action.yml | 2 +- webrtc-jni/build.gradle.kts | 32 ++++++++------------------------ 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index 68fd025..3f7f77c 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -17,7 +17,7 @@ runs: steps: - name: Create WebRTC checkout folder run: | - mkdir -p $HOME/webrtc + mkdir -p $HOME/webrtc/build echo "WEBRTC_CHECKOUT_FOLDER=$HOME/webrtc" >> $GITHUB_ENV shell: bash diff --git a/webrtc-jni/build.gradle.kts b/webrtc-jni/build.gradle.kts index dd0c203..40b3165 100644 --- a/webrtc-jni/build.gradle.kts +++ b/webrtc-jni/build.gradle.kts @@ -14,10 +14,9 @@ val currentOs = OperatingSystem.current() var targetPlatform = System.getenv("WEBRTC_PLATFORM") as? String -val hostArch = System.getProperty("os.arch").lowercase().trim() -val isHostArm = hostArch == "aarch64" || hostArch == "arm64" - if (targetPlatform == null) { + val rawArch = System.getProperty("os.arch").lowercase().trim() + val osFamily = when { currentOs.isLinux -> "linux" currentOs.isMacOsX -> "macos" @@ -26,21 +25,16 @@ if (targetPlatform == null) { } val osArch = when { - hostArch == "amd64" || hostArch == "x86_64" || hostArch == "x86-64" -> "x86_64" - isHostArm -> "aarch64" - hostArch.startsWith("arm") -> "aarch32" - else -> error("Unsupported Architecture: $hostArch") + rawArch == "amd64" || rawArch == "x86_64" || rawArch == "x86-64" -> "x86_64" + rawArch == "aarch64" || rawArch == "arm64" -> "aarch64" + rawArch.startsWith("arm") -> "aarch32" + else -> error("Unsupported Architecture: $rawArch") } targetPlatform = "$osFamily-$osArch" } -val useRosetta = currentOs.isMacOsX && isHostArm && targetPlatform == "macos-x86_64" - logger.lifecycle("Configuring webrtc-jni for Platform: $targetPlatform") -if (useRosetta) { - logger.lifecycle("Building for x86_64 on ARM host -> Using 'arch -x86_64'") -} val toolchainFile = file("src/main/cpp/toolchain").resolve( when { @@ -64,12 +58,7 @@ val configureNative by tasks.registering(Exec::class) { cmakeBuildDir.get().asFile.mkdirs() } - if (useRosetta) { - commandLine("arch", "-x86_64", "cmake") - } else { - commandLine("cmake") - } - + commandLine("cmake") args("-S", ".", "-B", cmakeBuildDir.get().asFile.absolutePath) args("-DCMAKE_BUILD_TYPE=Release") @@ -92,12 +81,7 @@ val buildNative by tasks.registering(Exec::class) { group = "build" dependsOn(configureNative) - if (useRosetta) { - commandLine("arch", "-x86_64", "cmake") - } else { - commandLine("cmake") - } - + commandLine("cmake") args("--build", cmakeBuildDir.get().asFile.absolutePath) args("--config", "Release") From ed8b82c3349e31a4957062de569872c72bb1c2f1 Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Thu, 25 Dec 2025 20:33:00 -0800 Subject: [PATCH 56/81] Add windows arm comp Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/workflows/build.yml | 2 ++ webrtc-jni/build.gradle.kts | 5 +++++ .../src/main/cpp/toolchain/aarch64-windows-clang.cmake | 5 +++++ webrtc-jni/src/main/cpp/toolchain/x86_64-windows-clang.cmake | 4 ++++ 4 files changed, 16 insertions(+) create mode 100644 webrtc-jni/src/main/cpp/toolchain/aarch64-windows-clang.cmake diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ee1e5a1..3ff8ce0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,6 +22,8 @@ jobs: platform: - name: windows-x86_64 runs-on: windows-2022 + - name: windows-aarch64 + runs-on: windows-2022 java: [17] runs-on: ${{ matrix.platform.runs-on }} steps: diff --git a/webrtc-jni/build.gradle.kts b/webrtc-jni/build.gradle.kts index 40b3165..d16da54 100644 --- a/webrtc-jni/build.gradle.kts +++ b/webrtc-jni/build.gradle.kts @@ -42,6 +42,7 @@ val toolchainFile = file("src/main/cpp/toolchain").resolve( targetPlatform == "linux-aarch64" -> "aarch64-linux-clang.cmake" targetPlatform == "linux-aarch32" -> "aarch32-linux-clang.cmake" targetPlatform == "windows-x86_64" -> "x86_64-windows-clang.cmake" + targetPlatform == "windows-aarch64" -> "aarch64-windows-clang.cmake" targetPlatform == "macos-x86_64" -> "x86_64-macos-cross.cmake" targetPlatform == "macos-aarch64" -> "aarch64-macos-clang.cmake" else -> "unknown-toolchain.cmake" @@ -62,6 +63,10 @@ val configureNative by tasks.registering(Exec::class) { args("-S", ".", "-B", cmakeBuildDir.get().asFile.absolutePath) args("-DCMAKE_BUILD_TYPE=Release") + if (targetPlatform == "windows-aarch64") { + args("-A", "ARM64") + } + if (toolchainFile.exists()) { logger.lifecycle("Using Toolchain file: ${toolchainFile.absolutePath}") args("-DWEBRTC_TOOLCHAIN_FILE=${toolchainFile.absolutePath}") diff --git a/webrtc-jni/src/main/cpp/toolchain/aarch64-windows-clang.cmake b/webrtc-jni/src/main/cpp/toolchain/aarch64-windows-clang.cmake new file mode 100644 index 0000000..2a198f7 --- /dev/null +++ b/webrtc-jni/src/main/cpp/toolchain/aarch64-windows-clang.cmake @@ -0,0 +1,5 @@ +set(CMAKE_SYSTEM_NAME Windows) +set(CMAKE_SYSTEM_PROCESSOR aarch64) +set(TARGET_CPU "arm64") + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MT /EHsc -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -D_LIBCPP_BUILDING_LIBRARY -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE") \ No newline at end of file diff --git a/webrtc-jni/src/main/cpp/toolchain/x86_64-windows-clang.cmake b/webrtc-jni/src/main/cpp/toolchain/x86_64-windows-clang.cmake index 2825309..3d079b4 100644 --- a/webrtc-jni/src/main/cpp/toolchain/x86_64-windows-clang.cmake +++ b/webrtc-jni/src/main/cpp/toolchain/x86_64-windows-clang.cmake @@ -1 +1,5 @@ +set(CMAKE_SYSTEM_NAME Windows) +set(CMAKE_SYSTEM_PROCESSOR x86_64) +set(TARGET_CPU "x64") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MT /EHsc -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -D_LIBCPP_BUILDING_LIBRARY -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE") From 6012b53a7c2f603455a4249f5e49153ea03d29cc Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Thu, 25 Dec 2025 20:34:05 -0800 Subject: [PATCH 57/81] Skip tests on arm windows Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/build/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index 3f7f77c..202d833 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -41,7 +41,7 @@ runs: - name: Build env: WEBRTC_PLATFORM: ${{ inputs.platform-name }} - SKIP_TESTS: ${{ inputs.platform-name == 'linux-aarch32' || inputs.platform-name == 'linux-aarch64' || inputs.platform-name == 'macos-x86_64' }} + SKIP_TESTS: ${{ inputs.platform-name == 'linux-aarch32' || inputs.platform-name == 'linux-aarch64' || inputs.platform-name == 'macos-x86_64' || inputs.platform-name == 'windows-aarch64' }} run: ./gradlew build shell: bash From c6d3d95f767994318965944157d4107086ad800b Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Thu, 25 Dec 2025 21:36:58 -0800 Subject: [PATCH 58/81] Fix windows compile Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- webrtc-jni/src/main/cpp/CMakeLists.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/webrtc-jni/src/main/cpp/CMakeLists.txt b/webrtc-jni/src/main/cpp/CMakeLists.txt index b730fe1..b4d0b7d 100644 --- a/webrtc-jni/src/main/cpp/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/CMakeLists.txt @@ -78,7 +78,14 @@ list(APPEND SOURCES add_library(${PROJECT_NAME} SHARED ${SOURCES}) # Introduced since WebRTC branch 7204 and Clang 20. -target_compile_options(${PROJECT_NAME} PRIVATE -Wno-nullability-completeness) +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + if(MSVC) + # clang-cl on Windows requires the /clang: prefix to avoid interpreting /W... as a warning level flag + target_compile_options(${PROJECT_NAME} PRIVATE /clang:-Wno-nullability-completeness) + else() + target_compile_options(${PROJECT_NAME} PRIVATE -Wno-nullability-completeness) + endif() +endif() target_include_directories(${PROJECT_NAME} PRIVATE From 6c8ca3e79b9905bcf689836e222580053ea19bb9 Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Thu, 25 Dec 2025 22:43:14 -0800 Subject: [PATCH 59/81] Decouple tests Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/build/action.yml | 7 ++- .github/actions/test/action.yml | 40 ++++++++++++++ .github/workflows/build.yml | 90 +++++++++++++++++++++++++++++--- .vscode/settings.json | 13 ++++- webrtc-jni/build.gradle.kts | 2 + webrtc/build.gradle.kts | 20 +++---- 6 files changed, 153 insertions(+), 19 deletions(-) create mode 100644 .github/actions/test/action.yml diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index 202d833..21ae138 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -41,8 +41,11 @@ runs: - name: Build env: WEBRTC_PLATFORM: ${{ inputs.platform-name }} - SKIP_TESTS: ${{ inputs.platform-name == 'linux-aarch32' || inputs.platform-name == 'linux-aarch64' || inputs.platform-name == 'macos-x86_64' || inputs.platform-name == 'windows-aarch64' }} - run: ./gradlew build + run: ./gradlew build -x test + shell: bash + + - name: List WebRTC cache folder contents + run: find $WEBRTC_CHECKOUT_FOLDER/build -maxdepth 2 shell: bash - name: Archive webrtc-java diff --git a/.github/actions/test/action.yml b/.github/actions/test/action.yml new file mode 100644 index 0000000..09869a3 --- /dev/null +++ b/.github/actions/test/action.yml @@ -0,0 +1,40 @@ +name: "Gradle Test" + +description: "Test the platform dependent Java library" + +inputs: + java-version: + description: "The Java build version." + required: true + default: "17" + + platform-name: + description: "The target platform." + required: true + +runs: + using: "composite" + steps: + - uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e + # https://github.com/actions/setup-java/releases/latest + with: + distribution: "temurin" + java-version: ${{ inputs.java-version }} + + - uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 + # https://github.com/gradle/actions/releases/latest + with: + cache-read-only: true + + - name: Download JNI Artifact + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 + # https://github.com/actions/download-artifact/releases/latest + with: + name: webrtc-java-jni-${{ inputs.platform-name }} + path: artifacts + + - name: Test + run: | + JNI_PATH=$(find artifacts -name "*.jar") + ./gradlew test -PprebuiltJniPath="$JNI_PATH" + shell: bash diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3ff8ce0..9a05c12 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,14 +3,14 @@ name: Build on: push: branches: - - '**' + - "**" paths-ignore: - - '.github/ISSUE_TEMPLATE/*.yml' - - '.gitignore' - - 'CONTRIBUTING.md' - - 'LICENSE' - - 'NOTICE' - - 'README.md' + - ".github/ISSUE_TEMPLATE/*.yml" + - ".gitignore" + - "CONTRIBUTING.md" + - "LICENSE" + - "NOTICE" + - "README.md" pull_request: workflow_dispatch: @@ -42,6 +42,31 @@ jobs: java-version: ${{ matrix.java }} platform-name: ${{ matrix.platform.name }} + test-windows: + needs: build-windows + strategy: + fail-fast: false + matrix: + platform: + - name: windows-x86_64 + runs-on: [windows-2022, windows-2025] + - name: windows-11-arm + artifact-name: windows-aarch64 + runs-on: [windows-11-arm] + java: [17] + runs-on: ${{ matrix.platform.runs-on }} + steps: + - name: Checkout code + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 + # https://github.com/actions/checkout/releases/latest + + - id: gradle-test + name: Gradle test + uses: ./.github/actions/test + with: + java-version: ${{ matrix.java }} + platform-name: ${{ matrix.platform.name }} + build-linux: strategy: fail-fast: false @@ -71,6 +96,32 @@ jobs: java-version: ${{ matrix.java }} platform-name: ${{ matrix.platform.name }} + test-linux: + needs: build-linux + strategy: + fail-fast: false + matrix: + platform: + - name: linux-aarch32 + runs-on: [ubuntu-22.04-arm, ubuntu-24.04-arm] + - name: linux-aarch64 + runs-on: [ubuntu-22.04-arm, ubuntu-24.04-arm] + - name: linux-x86_64 + runs-on: [ubuntu-22.04, ubuntu-24.04] + java: [17] + runs-on: ${{ matrix.platform.runs-on }} + steps: + - name: Checkout code + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 + # https://github.com/actions/checkout/releases/latest + + - id: gradle-test + name: Gradle test + uses: ./.github/actions/test + with: + java-version: ${{ matrix.java }} + platform-name: ${{ matrix.platform.name }} + build-macos: strategy: fail-fast: false @@ -97,3 +148,28 @@ jobs: with: java-version: ${{ matrix.java }} platform-name: ${{ matrix.platform.name }} + + test-macos: + needs: build-macos + strategy: + fail-fast: false + matrix: + platform: + - name: macos-x86_64 + runs-on: [macos-15-intel] + - name: macos-aarch64 + runs-on: [macos-14, macos-15, macos-26] + java: [17] + runs-on: ${{ matrix.platform.runs-on }} + steps: + - name: Checkout code + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 + # https://github.com/actions/checkout/releases/latest + + - id: gradle-test + name: Gradle test + uses: ./.github/actions/test + with: + java-version: ${{ matrix.java }} + platform-name: ${{ matrix.platform.name }} + diff --git a/.vscode/settings.json b/.vscode/settings.json index 6d6682a..8b64f52 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,14 @@ { - "C_Cpp.intelliSenseEngine": "disabled" + "C_Cpp.intelliSenseEngine": "disabled", + "yaml.format.enable": true, + "[yaml]": { + "editor.defaultFormatter": "redhat.vscode-yaml", + "editor.tabSize": 2, + "editor.detectIndentation": false + }, + "[github-actions-workflow]": { + "editor.tabSize": 2, + "editor.autoIndent": "keep", + "editor.detectIndentation": false + } } \ No newline at end of file diff --git a/webrtc-jni/build.gradle.kts b/webrtc-jni/build.gradle.kts index d16da54..d75d6c1 100644 --- a/webrtc-jni/build.gradle.kts +++ b/webrtc-jni/build.gradle.kts @@ -79,6 +79,7 @@ val configureNative by tasks.registering(Exec::class) { args("-DWEBRTC_BRANCH=$webrtcBranch") args("-DOUTPUT_NAME_SUFFIX=$targetPlatform") + args("-DCMAKE_INSTALL_PREFIX=${layout.buildDirectory.dir("install").get().asFile.absolutePath}") args("-DCMAKE_EXPORT_COMPILE_COMMANDS=1") } @@ -89,6 +90,7 @@ val buildNative by tasks.registering(Exec::class) { commandLine("cmake") args("--build", cmakeBuildDir.get().asFile.absolutePath) args("--config", "Release") + args("--target", "install") if (!currentOs.isWindows) { args("-j", Runtime.getRuntime().availableProcessors()) diff --git a/webrtc/build.gradle.kts b/webrtc/build.gradle.kts index 7bb9849..cd49fa4 100644 --- a/webrtc/build.gradle.kts +++ b/webrtc/build.gradle.kts @@ -5,11 +5,20 @@ plugins { } dependencies { - api(project(":webrtc-jni")) + val prebuiltJniPath = project.findProperty("prebuiltJniPath") as? String + if (prebuiltJniPath != null) { + api(files(prebuiltJniPath)) + } else { + api(project(":webrtc-jni")) + } testImplementation(libs.bundles.junit) testRuntimeOnly(libs.junit.platform.launcher) - testRuntimeOnly(project(":webrtc-jni")) + if (prebuiltJniPath != null) { + testRuntimeOnly(files(prebuiltJniPath)) + } else { + testRuntimeOnly(project(":webrtc-jni")) + } } configure { @@ -26,13 +35,6 @@ tasks.named("test") { events("passed", "skipped", "failed") } } - -if (System.getenv("SKIP_TESTS") == "true") { - tasks.named("test") { - enabled = false - } -} - publishing { publications { create("maven") { From fa37898b0cb5f5db0feb1217dc7b167b0b292690 Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Fri, 26 Dec 2025 00:04:55 -0800 Subject: [PATCH 60/81] Fix test matricies Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/build/action.yml | 2 +- .github/actions/test/action.yml | 2 +- .github/workflows/build.yml | 58 ++++++++++++++++++++++---------- webrtc/build.gradle.kts | 1 + 4 files changed, 44 insertions(+), 19 deletions(-) diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index 21ae138..07f9461 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -32,7 +32,7 @@ runs: - uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # https://github.com/actions/setup-java/releases/latest with: - distribution: 'temurin' + distribution: "liberica" java-version: ${{ inputs.java-version }} - uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 diff --git a/.github/actions/test/action.yml b/.github/actions/test/action.yml index 09869a3..0bca7a3 100644 --- a/.github/actions/test/action.yml +++ b/.github/actions/test/action.yml @@ -18,7 +18,7 @@ runs: - uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # https://github.com/actions/setup-java/releases/latest with: - distribution: "temurin" + distribution: "liberica" java-version: ${{ inputs.java-version }} - uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9a05c12..256271c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -48,11 +48,15 @@ jobs: fail-fast: false matrix: platform: - - name: windows-x86_64 - runs-on: [windows-2022, windows-2025] - - name: windows-11-arm + - name: windows-2022_windows-x86_64 + artifact-name: windows-x86_64 + runs-on: windows-2022 + - name: windows-2025_windows-x86_64 + artifact-name: windows-x86_64 + runs-on: windows-2025 + - name: windows-11-arm_windows-aarch64 artifact-name: windows-aarch64 - runs-on: [windows-11-arm] + runs-on: windows-11-arm java: [17] runs-on: ${{ matrix.platform.runs-on }} steps: @@ -65,7 +69,7 @@ jobs: uses: ./.github/actions/test with: java-version: ${{ matrix.java }} - platform-name: ${{ matrix.platform.name }} + platform-name: ${{ matrix.platform.artifact-name }} build-linux: strategy: @@ -102,12 +106,24 @@ jobs: fail-fast: false matrix: platform: - - name: linux-aarch32 - runs-on: [ubuntu-22.04-arm, ubuntu-24.04-arm] - - name: linux-aarch64 - runs-on: [ubuntu-22.04-arm, ubuntu-24.04-arm] - - name: linux-x86_64 - runs-on: [ubuntu-22.04, ubuntu-24.04] + - name: ubuntu-22.04-arm_linux-aarch32 + artifact-name: linux-aarch32 + runs-on: ubuntu-22.04-arm + - name: ubuntu-24.04-arm_linux-aarch32 + artifact-name: linux-aarch32 + runs-on: ubuntu-24.04-arm + - name: ubuntu-22.04-arm_linux-aarch64 + artifact-name: linux-aarch64 + runs-on: ubuntu-22.04-arm + - name: ubuntu-24.04-arm_linux-aarch64 + artifact-name: linux-aarch64 + runs-on: ubuntu-24.04-arm + - name: ubuntu-22.04_linux-x86_64 + artifact-name: linux-x86_64 + runs-on: ubuntu-22.04 + - name: ubuntu-24.04_linux-x86_64 + artifact-name: linux-x86_64 + runs-on: ubuntu-24.04 java: [17] runs-on: ${{ matrix.platform.runs-on }} steps: @@ -120,7 +136,7 @@ jobs: uses: ./.github/actions/test with: java-version: ${{ matrix.java }} - platform-name: ${{ matrix.platform.name }} + platform-name: ${{ matrix.platform.artifact-name }} build-macos: strategy: @@ -155,10 +171,18 @@ jobs: fail-fast: false matrix: platform: - - name: macos-x86_64 - runs-on: [macos-15-intel] - - name: macos-aarch64 - runs-on: [macos-14, macos-15, macos-26] + - name: macos-15-intel_macos-x86_64 + artifact-name: macos-x86_64 + runs-on: macos-15-intel + - name: macos-14_macos-aarch64 + artifact-name: macos-aarch64 + runs-on: macos-14 + - name: macos-15_macos-aarch64 + artifact-name: macos-aarch64 + runs-on: macos-15 + - name: macos-26_macos-aarch64 + artifact-name: macos-aarch64 + runs-on: macos-26-intel java: [17] runs-on: ${{ matrix.platform.runs-on }} steps: @@ -171,5 +195,5 @@ jobs: uses: ./.github/actions/test with: java-version: ${{ matrix.java }} - platform-name: ${{ matrix.platform.name }} + platform-name: ${{ matrix.platform.artifact-name }} diff --git a/webrtc/build.gradle.kts b/webrtc/build.gradle.kts index cd49fa4..54d8aa2 100644 --- a/webrtc/build.gradle.kts +++ b/webrtc/build.gradle.kts @@ -8,6 +8,7 @@ dependencies { val prebuiltJniPath = project.findProperty("prebuiltJniPath") as? String if (prebuiltJniPath != null) { api(files(prebuiltJniPath)) + logger.lifecycle("Using prebuilt webrtc-jni from: $prebuiltJniPath") } else { api(project(":webrtc-jni")) } From 648cf3eee114e1c11de7f645d27ba7c50d4f1853 Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Fri, 26 Dec 2025 00:18:49 -0800 Subject: [PATCH 61/81] Attempt to fix tests Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/build/action.yml | 4 ---- webrtc-jni/build.gradle.kts | 10 +++++++--- webrtc/build.gradle.kts | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index 07f9461..80c3157 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -44,10 +44,6 @@ runs: run: ./gradlew build -x test shell: bash - - name: List WebRTC cache folder contents - run: find $WEBRTC_CHECKOUT_FOLDER/build -maxdepth 2 - shell: bash - - name: Archive webrtc-java uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # https://github.com/actions/upload-artifact/releases/latest diff --git a/webrtc-jni/build.gradle.kts b/webrtc-jni/build.gradle.kts index d75d6c1..b3fdad4 100644 --- a/webrtc-jni/build.gradle.kts +++ b/webrtc-jni/build.gradle.kts @@ -105,7 +105,7 @@ val copyNativeLibs by tasks.registering(Copy::class) { exclude("**/*.lib", "**/*.exp", "**/obj/**", "**/CMakeFiles/**") }) - into(layout.buildDirectory.dir("resources/main")) + into(layout.buildDirectory.dir("generated/jni")) rename { filename -> if (filename.contains("webrtc-java")) { @@ -120,8 +120,12 @@ val copyNativeLibs by tasks.registering(Copy::class) { eachFile { relativePath = RelativePath(true, name) } } -tasks.named("processResources") { - dependsOn(copyNativeLibs) +sourceSets { + main { + resources { + srcDir(copyNativeLibs) + } + } } tasks.named("jar") { diff --git a/webrtc/build.gradle.kts b/webrtc/build.gradle.kts index 54d8aa2..cd07cd4 100644 --- a/webrtc/build.gradle.kts +++ b/webrtc/build.gradle.kts @@ -26,7 +26,7 @@ configure { toolchain.languageVersion.set(JavaLanguageVersion.of(17)) withJavadocJar() withSourcesJar() - modularity.inferModulePath.set(true) + modularity.inferModulePath.set(false) } tasks.named("test") { From 362bb2e9f080f967f6c8d540681b42729739f82f Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Fri, 26 Dec 2025 00:49:53 -0800 Subject: [PATCH 62/81] Provide full path for test artifacts Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/build/action.yml | 4 ++-- .github/workflows/build.yml | 2 +- webrtc/build.gradle.kts | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index 80c3157..9ad8a61 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -17,8 +17,8 @@ runs: steps: - name: Create WebRTC checkout folder run: | - mkdir -p $HOME/webrtc/build - echo "WEBRTC_CHECKOUT_FOLDER=$HOME/webrtc" >> $GITHUB_ENV + mkdir -p ~/webrtc/build + echo "WEBRTC_CHECKOUT_FOLDER=~/webrtc" >> $GITHUB_ENV shell: bash - name: Set up WebRTC cache diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 256271c..5498a6e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -182,7 +182,7 @@ jobs: runs-on: macos-15 - name: macos-26_macos-aarch64 artifact-name: macos-aarch64 - runs-on: macos-26-intel + runs-on: macos-26 java: [17] runs-on: ${{ matrix.platform.runs-on }} steps: diff --git a/webrtc/build.gradle.kts b/webrtc/build.gradle.kts index cd07cd4..3be8f9c 100644 --- a/webrtc/build.gradle.kts +++ b/webrtc/build.gradle.kts @@ -26,12 +26,13 @@ configure { toolchain.languageVersion.set(JavaLanguageVersion.of(17)) withJavadocJar() withSourcesJar() - modularity.inferModulePath.set(false) } tasks.named("test") { useJUnitPlatform() + modularity.inferModulePath.set(false) + testLogging { events("passed", "skipped", "failed") } From bd823ac7183eda53b43c9b8a8f61add6fc64cdb7 Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Fri, 26 Dec 2025 01:01:45 -0800 Subject: [PATCH 63/81] Use full path Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/build/action.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index 9ad8a61..5190e72 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -17,8 +17,8 @@ runs: steps: - name: Create WebRTC checkout folder run: | - mkdir -p ~/webrtc/build - echo "WEBRTC_CHECKOUT_FOLDER=~/webrtc" >> $GITHUB_ENV + mkdir -p $HOME/webrtc/build + echo "WEBRTC_CHECKOUT_FOLDER=$HOME/webrtc" >> $GITHUB_ENV shell: bash - name: Set up WebRTC cache @@ -26,6 +26,7 @@ runs: # https://github.com/actions/cache/releases/latest with: path: ${{ env.WEBRTC_CHECKOUT_FOLDER }}/build + shell: bash key: webrtc-${{ hashFiles('webrtc-jni/gradle.properties') }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt') }} restore-keys: webrtc-${{ hashFiles('webrtc-jni/gradle.properties') }}-${{ inputs.platform-name }}- From 99c3a5bb41eb13483b584d6738af011d5486b7d8 Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Fri, 26 Dec 2025 01:03:41 -0800 Subject: [PATCH 64/81] Try shell bash for actions/cache Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/build/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index 5190e72..d154d11 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -24,9 +24,9 @@ runs: - name: Set up WebRTC cache uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # https://github.com/actions/cache/releases/latest + shell: bash with: path: ${{ env.WEBRTC_CHECKOUT_FOLDER }}/build - shell: bash key: webrtc-${{ hashFiles('webrtc-jni/gradle.properties') }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt') }} restore-keys: webrtc-${{ hashFiles('webrtc-jni/gradle.properties') }}-${{ inputs.platform-name }}- From f5bded1b6d38660f46fec9e9c912dea4e5ecd1ec Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Fri, 26 Dec 2025 01:23:47 -0800 Subject: [PATCH 65/81] Downgrade cache action... Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/build/action.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index d154d11..a45c4cc 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -22,9 +22,8 @@ runs: shell: bash - name: Set up WebRTC cache - uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # https://github.com/actions/cache/releases/latest - shell: bash with: path: ${{ env.WEBRTC_CHECKOUT_FOLDER }}/build key: webrtc-${{ hashFiles('webrtc-jni/gradle.properties') }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt') }} From 92dc987eaebbe44e16278e627133d3e58ebe6517 Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Fri, 26 Dec 2025 01:28:38 -0800 Subject: [PATCH 66/81] Use full path (actually) Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/test/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/test/action.yml b/.github/actions/test/action.yml index 0bca7a3..d55143b 100644 --- a/.github/actions/test/action.yml +++ b/.github/actions/test/action.yml @@ -35,6 +35,6 @@ runs: - name: Test run: | - JNI_PATH=$(find artifacts -name "*.jar") + JNI_PATH=$(find ~+/artifacts -name "*.jar") ./gradlew test -PprebuiltJniPath="$JNI_PATH" shell: bash From a9d7c25588df5770e50565f217b07837578e274c Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Fri, 26 Dec 2025 01:35:28 -0800 Subject: [PATCH 67/81] Only do webrtc test task Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/test/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/test/action.yml b/.github/actions/test/action.yml index d55143b..319a944 100644 --- a/.github/actions/test/action.yml +++ b/.github/actions/test/action.yml @@ -36,5 +36,5 @@ runs: - name: Test run: | JNI_PATH=$(find ~+/artifacts -name "*.jar") - ./gradlew test -PprebuiltJniPath="$JNI_PATH" + ./gradlew :webrtc:test -PprebuiltJniPath="$JNI_PATH" shell: bash From 65ce2107c868e92533270ad78af8983b119b45e3 Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Fri, 26 Dec 2025 02:09:13 -0800 Subject: [PATCH 68/81] Try arm32 tests Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/test/action.yml | 14 ++++++++++++++ .github/workflows/build.yml | 7 +++++++ 2 files changed, 21 insertions(+) diff --git a/.github/actions/test/action.yml b/.github/actions/test/action.yml index 319a944..1da8b0d 100644 --- a/.github/actions/test/action.yml +++ b/.github/actions/test/action.yml @@ -12,14 +12,28 @@ inputs: description: "The target platform." required: true + architecture: + description: "The target architecture." + required: false + default: "" + runs: using: "composite" steps: + - name: Install 32-bit ARM libraries + if: inputs.architecture == 'armv7' + run: | + sudo dpkg --add-architecture armhf + sudo apt-get update + sudo apt-get install -y libc6:armhf libstdc++6:armhf + shell: bash + - uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # https://github.com/actions/setup-java/releases/latest with: distribution: "liberica" java-version: ${{ inputs.java-version }} + architecture: ${{ inputs.architecture }} - uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 # https://github.com/gradle/actions/releases/latest diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5498a6e..a685079 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -109,21 +109,27 @@ jobs: - name: ubuntu-22.04-arm_linux-aarch32 artifact-name: linux-aarch32 runs-on: ubuntu-22.04-arm + java-arch: armv7 - name: ubuntu-24.04-arm_linux-aarch32 artifact-name: linux-aarch32 runs-on: ubuntu-24.04-arm + java-arch: armv7 - name: ubuntu-22.04-arm_linux-aarch64 artifact-name: linux-aarch64 runs-on: ubuntu-22.04-arm + java-arch: aarch64 - name: ubuntu-24.04-arm_linux-aarch64 artifact-name: linux-aarch64 runs-on: ubuntu-24.04-arm + java-arch: aarch64 - name: ubuntu-22.04_linux-x86_64 artifact-name: linux-x86_64 runs-on: ubuntu-22.04 + java-arch: x64 - name: ubuntu-24.04_linux-x86_64 artifact-name: linux-x86_64 runs-on: ubuntu-24.04 + java-arch: x64 java: [17] runs-on: ${{ matrix.platform.runs-on }} steps: @@ -137,6 +143,7 @@ jobs: with: java-version: ${{ matrix.java }} platform-name: ${{ matrix.platform.artifact-name }} + architecture: ${{ matrix.platform.java-arch }} build-macos: strategy: From a72424fd8c538c6e220ac36956b01c019fb40b9f Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Fri, 26 Dec 2025 02:19:49 -0800 Subject: [PATCH 69/81] try to debug 32 bit linux Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/test/action.yml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/actions/test/action.yml b/.github/actions/test/action.yml index 1da8b0d..203cdb7 100644 --- a/.github/actions/test/action.yml +++ b/.github/actions/test/action.yml @@ -25,7 +25,7 @@ runs: run: | sudo dpkg --add-architecture armhf sudo apt-get update - sudo apt-get install -y libc6:armhf libstdc++6:armhf + sudo apt-get install -y libc6:armhf libstdc++6:armhf zlib1g:armhf shell: bash - uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e @@ -35,6 +35,18 @@ runs: java-version: ${{ inputs.java-version }} architecture: ${{ inputs.architecture }} + - name: Debug 32-bit environment + if: inputs.architecture == 'armv7' + run: | + echo "Checking for dynamic loader..." + ls -l /lib/ld-linux-armhf.so.3 || echo "Loader not found in /lib" + ls -l /usr/lib/arm-linux-gnueabihf/ || echo "Library path not found" + + echo "Checking binary dependencies..." + JAVA_BIN=$(find /opt/hostedtoolcache -name java | grep armv7 | head -n 1) + readelf -l "$JAVA_BIN" | grep "interpreter" + shell: bash + - uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 # https://github.com/gradle/actions/releases/latest with: From 4de1aef1aa91259e3b1367892e6b77b2527aedcd Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Fri, 26 Dec 2025 02:28:02 -0800 Subject: [PATCH 70/81] More 32-bit changes Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/test/action.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/actions/test/action.yml b/.github/actions/test/action.yml index 203cdb7..bb98163 100644 --- a/.github/actions/test/action.yml +++ b/.github/actions/test/action.yml @@ -62,5 +62,8 @@ runs: - name: Test run: | JNI_PATH=$(find ~+/artifacts -name "*.jar") - ./gradlew :webrtc:test -PprebuiltJniPath="$JNI_PATH" + ./gradlew :webrtc:test -PprebuiltJniPath="$JNI_PATH" \ + --no-daemon \ + -Dorg.gradle.vfs.watch=false \ + --stacktrace shell: bash From f648ea0720f1b667d2f18c1bc5f6ec797649e3b8 Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Fri, 26 Dec 2025 02:37:20 -0800 Subject: [PATCH 71/81] More arm32 test changes Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/build/action.yml | 2 +- .github/actions/test/action.yml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index a45c4cc..2117a17 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -22,7 +22,7 @@ runs: shell: bash - name: Set up WebRTC cache - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 + uses: actions/cache@6f8efc29b200d32929f49075959781ed54ec270c # https://github.com/actions/cache/releases/latest with: path: ${{ env.WEBRTC_CHECKOUT_FOLDER }}/build diff --git a/.github/actions/test/action.yml b/.github/actions/test/action.yml index bb98163..cc31a0e 100644 --- a/.github/actions/test/action.yml +++ b/.github/actions/test/action.yml @@ -64,6 +64,8 @@ runs: JNI_PATH=$(find ~+/artifacts -name "*.jar") ./gradlew :webrtc:test -PprebuiltJniPath="$JNI_PATH" \ --no-daemon \ + --console=plain \ + -Dorg.gradle.native=false \ -Dorg.gradle.vfs.watch=false \ --stacktrace shell: bash From 34087bb72bb9069990fea44c3f348bc21e1c6cf1 Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Fri, 26 Dec 2025 02:47:36 -0800 Subject: [PATCH 72/81] Try cache with tilde Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/build/action.yml | 4 ++-- .github/actions/test/action.yml | 12 ------------ 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index 2117a17..71e4188 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -17,8 +17,8 @@ runs: steps: - name: Create WebRTC checkout folder run: | - mkdir -p $HOME/webrtc/build - echo "WEBRTC_CHECKOUT_FOLDER=$HOME/webrtc" >> $GITHUB_ENV + mkdir -p ~/webrtc/build + echo "WEBRTC_CHECKOUT_FOLDER=~/webrtc" >> $GITHUB_ENV shell: bash - name: Set up WebRTC cache diff --git a/.github/actions/test/action.yml b/.github/actions/test/action.yml index cc31a0e..2dcbd5d 100644 --- a/.github/actions/test/action.yml +++ b/.github/actions/test/action.yml @@ -35,18 +35,6 @@ runs: java-version: ${{ inputs.java-version }} architecture: ${{ inputs.architecture }} - - name: Debug 32-bit environment - if: inputs.architecture == 'armv7' - run: | - echo "Checking for dynamic loader..." - ls -l /lib/ld-linux-armhf.so.3 || echo "Loader not found in /lib" - ls -l /usr/lib/arm-linux-gnueabihf/ || echo "Library path not found" - - echo "Checking binary dependencies..." - JAVA_BIN=$(find /opt/hostedtoolcache -name java | grep armv7 | head -n 1) - readelf -l "$JAVA_BIN" | grep "interpreter" - shell: bash - - uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 # https://github.com/gradle/actions/releases/latest with: From a25aa79086d3856947d96e5a0baaab985a273f7f Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Fri, 26 Dec 2025 16:00:55 -0800 Subject: [PATCH 73/81] Update publishing and README Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/prepare-macos/action.yml | 4 +- README.md | 50 ++++++++++++------------ build.gradle.kts | 8 +++- gradle/libs.versions.toml | 5 ++- webrtc-jni/build.gradle.kts | 39 +++++++++++++----- webrtc/build.gradle.kts | 43 ++++++++++++++------ webrtc/src/main/java/module-info.java | 2 +- 7 files changed, 100 insertions(+), 51 deletions(-) diff --git a/.github/actions/prepare-macos/action.yml b/.github/actions/prepare-macos/action.yml index 58733af..599cf48 100644 --- a/.github/actions/prepare-macos/action.yml +++ b/.github/actions/prepare-macos/action.yml @@ -1,6 +1,6 @@ -name: 'Prepare macOS Build' +name: "Prepare macOS Build" -description: 'Installs required packages for macOS builds.' +description: "Installs required packages for macOS builds." runs: using: "composite" diff --git a/README.md b/README.md index 1dc97a3..108270b 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,43 @@ -[![Build Status](https://img.shields.io/github/actions/workflow/status/devopvoid/webrtc-java/build.yml?label=Build&logo=github)](https://github.com/devopvoid/webrtc-java/actions) -[![Maven Central](https://img.shields.io/maven-central/v/dev.kastle.webrtc/webrtc-java?label=Maven%20Central&logo=apache-maven)](https://search.maven.org/artifact/dev.kastle.webrtc/webrtc-java) +This is a fork of devopvoid's [webrtc-java](https://github.com/devopvoid/webrtc-java) library, a Java wrapper for the [WebRTC Native API](https://webrtc.github.io/webrtc-org/native-code/native-apis). -

    - webrtc-java -

    Connecting the Java world through WebRTC

    -

    +## Differences from the Original Project -webrtc-java is a Java wrapper for the [WebRTC Native API](https://webrtc.github.io/webrtc-org/native-code/native-apis), providing similar functionality to the [W3C JavaScript API](https://w3c.github.io/webrtc-pc). It allows Java developers to build real-time communication applications for desktop platforms without having to work directly with native code. +This stripped down version of the library removes audio and video support, focusing solely on data channels for peer-to-peer data exchange. It is intended for use cases where only data transfer is required, such as multiplayer gaming or real-time data synchronization. The removal of media capabilities results in a significantly smaller library size and increased portability. -The library provides a comprehensive set of Java classes that map to the WebRTC C++ API, making it possible to establish peer-to-peer connections, transmit audio and video, share screens, and exchange arbitrary data between applications. +It also adds support for ARM Windows systems, and has testing coverage for all platforms via GitHub Actions. -## Features +## Usage -- **Complete WebRTC API implementation** - Includes peer connections, media devices, data channels, and more -- **Cross-platform support** - Works on Windows, macOS, and Linux (x64, ARM, ARM64) -- **Media capabilities** - Audio and video capture from cameras and microphones -- **Desktop capture** - Screen and application window sharing -- **Data channels** - Bidirectional peer-to-peer data exchange -- **Statistics API** - Detailed metrics for monitoring connection quality -- **Simple integration** - Available as a Maven dependency -- **Native performance** - Thin JNI layer with minimal overhead +The base project is published under the group `dev.kastle.webrtc` and artifact `webrtc-java`. The native libraries are published under the same group and artifact with platform-specific classifiers: -## Getting Started +- `linux-x86_64` +- `linux-aarch32` +- `linux-aarch64` +- `windows-x86_64` +- `windows-aarch64` +- `macos-x86_64` +- `macos-aarch64` -For more detailed information, check out the documentation: +Note that the natives are not bundled with the main library, so you will need to appropriately include those that are needed for your project. If your project is an executable jar, you may want to read [JEP-472](https://openjdk.org/jeps/472). Because this project uses JNI, you may need to enable native access, depending on your Java version and execution environment. The main module is named `dev.kastle.webrtc`, and the natives modules are named `dev.kastle.webrtc.natives.` (e.g. `dev.kastle.webrtc.natives.linux.x86_64`), with any hyphens replaced by periods. -- [Quickstart](https://jrtc.dev/guide/get-started) - Get up and running quickly with webrtc-java -- [Guides](https://jrtc.dev/guide/) - Comprehensive documentation on using the library -- [Examples](https://jrtc.dev/guide/examples) - Sample code demonstrating various features -- [Build Notes](https://jrtc.dev/guide/build) - Instructions for building the library from source +## Development + +The project has a preconfigured `.vscode` setup for easy development. Make sure to install the recommended extensions when prompted. Run the `./gradlew build` command to build the project. Note that building the native libraries requires [clang](https://clang.llvm.org/get_started.html) and [cmake](https://cmake.org/download/) to be installed and on your path. + +The initial build will take significant time to compile, as cloning the WebRTC source code brings in multiple other repo source trees from the Chromium project, requiring about 20 GB of disk space. On Windows, you may need to set `WEBRTC_CHECKOUT_FOLDER` to a shorter path to avoid exceeding file path length limits. + +The version of WebRTC used can be changed by modifying the `webrtc.branch` property in [`webrtc-jni/gradle.properties`](webrtc-jni/gradle.properties). Note, however, that changing the version used will likely require updating the patches in [`webrtc-jni/src/main/cpp/dependencies/webrtc/patches/`](webrtc-jni/src/main/cpp/dependencies/webrtc/patches/) to ensure successful compilation. ## License +This copyright notice is maintained from the original project: + +```md Copyright (c) 2019 Alex Andres Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0) -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. \ No newline at end of file +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +``` \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 56499ef..a3d6e0e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - alias(libs.plugins.nmcp) + alias(libs.plugins.nmcp.aggregation) `maven-publish` `eclipse` } @@ -13,6 +13,12 @@ allprojects { } } +dependencies { + allprojects { + nmcpAggregation(project(path)) + } +} + nmcpAggregation { centralPortal { project(":webrtc") diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7a27fb6..d4c0346 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -nmcp = "1.3.0" +nmcp = "1.4.0" cmakePlugin = "0.9.6" junit = "5.14.1" @@ -14,5 +14,6 @@ junit-platform-launcher = { group = "org.junit.platform", name = "junit-platform junit = ["junit-jupiter-engine", "junit-jupiter-api", "junit-jupiter-params", "junit-platform-launcher"] [plugins] -nmcp = { id = "com.gradleup.nmcp.aggregation", version.ref = "nmcp" } +nmcp = { id = "com.gradleup.nmcp", version.ref = "nmcp" } +nmcp-aggregation = { id = "com.gradleup.nmcp.aggregation", version.ref = "nmcp" } cmake = { id = "io.github.tomaki19.gradle-cmake-plugin", version.ref = "cmakePlugin" } \ No newline at end of file diff --git a/webrtc-jni/build.gradle.kts b/webrtc-jni/build.gradle.kts index b3fdad4..d1d64be 100644 --- a/webrtc-jni/build.gradle.kts +++ b/webrtc-jni/build.gradle.kts @@ -1,5 +1,8 @@ import org.gradle.internal.os.OperatingSystem +import java.time.ZonedDateTime +import java.time.format.DateTimeFormatter + plugins { `java` } @@ -34,8 +37,6 @@ if (targetPlatform == null) { targetPlatform = "$osFamily-$osArch" } -logger.lifecycle("Configuring webrtc-jni for Platform: $targetPlatform") - val toolchainFile = file("src/main/cpp/toolchain").resolve( when { targetPlatform == "linux-x86_64" -> "x86_64-linux-clang.cmake" @@ -52,6 +53,8 @@ val toolchainFile = file("src/main/cpp/toolchain").resolve( val cmakeBuildDir = layout.buildDirectory.dir("cmake/$targetPlatform") val configureNative by tasks.registering(Exec::class) { + logger.lifecycle("Configuring webrtc-jni for Platform: $targetPlatform") + group = "build" workingDir = file("src/main/cpp") @@ -99,6 +102,7 @@ val buildNative by tasks.registering(Exec::class) { val copyNativeLibs by tasks.registering(Copy::class) { dependsOn(buildNative) + includeEmptyDirs = false from(fileTree(cmakeBuildDir).matching { include("**/*.so", "**/*.dll", "**/*.dylib") @@ -120,17 +124,32 @@ val copyNativeLibs by tasks.registering(Copy::class) { eachFile { relativePath = RelativePath(true, name) } } -sourceSets { - main { - resources { - srcDir(copyNativeLibs) - } - } -} - tasks.named("jar") { archiveBaseName.set("webrtc-java") archiveClassifier.set(targetPlatform) + + from(copyNativeLibs) { + into("/") + } + + manifest { + val safePlatformName = targetPlatform?.replace("-", ".") ?: "unknown" + + attributes( + "Manifest-Version" to "1.0", + + "Implementation-Title" to "WebRTC Java Natives ($targetPlatform)", + "Implementation-Version" to project.version, + "Implementation-Vendor" to "Kas-tle", + + "Automatic-Module-Name" to "dev.kastle.webrtc.natives.$safePlatformName", + + "Created-By" to "Gradle ${gradle.gradleVersion}", + "Build-Jdk-Spec" to "17", + "Build-Date" to ZonedDateTime.now().format(DateTimeFormatter.ISO_INSTANT), + "Build-Platform" to targetPlatform!! + ) + } } tasks.withType { enabled = false } \ No newline at end of file diff --git a/webrtc/build.gradle.kts b/webrtc/build.gradle.kts index 3be8f9c..7ad8c61 100644 --- a/webrtc/build.gradle.kts +++ b/webrtc/build.gradle.kts @@ -1,24 +1,23 @@ +import java.time.ZonedDateTime +import java.time.format.DateTimeFormatter + plugins { + id("com.gradleup.nmcp") `java-library` `maven-publish` `signing` } dependencies { - val prebuiltJniPath = project.findProperty("prebuiltJniPath") as? String - if (prebuiltJniPath != null) { - api(files(prebuiltJniPath)) - logger.lifecycle("Using prebuilt webrtc-jni from: $prebuiltJniPath") - } else { - api(project(":webrtc-jni")) - } - testImplementation(libs.bundles.junit) testRuntimeOnly(libs.junit.platform.launcher) - if (prebuiltJniPath != null) { - testRuntimeOnly(files(prebuiltJniPath)) - } else { + + val prebuiltJniPath = project.findProperty("prebuiltJniPath") as? String + if (prebuiltJniPath == null) { testRuntimeOnly(project(":webrtc-jni")) + } else { + testRuntimeOnly(files(prebuiltJniPath)) + logger.lifecycle("Using prebuilt testing webrtc-jni from: $prebuiltJniPath") } } @@ -37,6 +36,28 @@ tasks.named("test") { events("passed", "skipped", "failed") } } + +tasks.named("jar") { + manifest { + attributes( + "Manifest-Version" to "1.0", + + "Implementation-Title" to "WebRTC Java", + "Implementation-Version" to project.version, + "Implementation-Vendor" to "Kas-tle", + + "Automatic-Module-Name" to "dev.kastle.webrtc", + + "Bundle-SymbolicName" to "dev.kastle.webrtc", + "Bundle-Version" to project.version, + + "Created-By" to "Gradle ${gradle.gradleVersion}", + "Build-Jdk-Spec" to "17", + "Build-Date" to ZonedDateTime.now().format(DateTimeFormatter.ISO_INSTANT) + ) + } +} + publishing { publications { create("maven") { diff --git a/webrtc/src/main/java/module-info.java b/webrtc/src/main/java/module-info.java index cf6b87c..798818d 100644 --- a/webrtc/src/main/java/module-info.java +++ b/webrtc/src/main/java/module-info.java @@ -1,4 +1,4 @@ -module webrtc.java { +module dev.kastle.webrtc { exports dev.kastle.webrtc; exports dev.kastle.webrtc.logging; } \ No newline at end of file From 9dce121e5a274c04e0c796cce4be7944dedf586c Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Fri, 26 Dec 2025 17:00:16 -0800 Subject: [PATCH 74/81] Update native publishing inclusion Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .gitignore | 3 +++ webrtc/build.gradle.kts | 47 +++++++++++++++++++++++++++-------------- 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index dd62756..ca2cf0f 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,6 @@ webrtc-jni/src/main/cpp/dependencies/webrtc/webrtc-source/ # VSCode / clangd .cache/ compile_commands.json + +# CI +native-staging/ \ No newline at end of file diff --git a/webrtc/build.gradle.kts b/webrtc/build.gradle.kts index 7ad8c61..9fcdbaf 100644 --- a/webrtc/build.gradle.kts +++ b/webrtc/build.gradle.kts @@ -1,3 +1,7 @@ +import kotlin.io.walk +import kotlin.io.walkTopDown + +import java.io.File import java.time.ZonedDateTime import java.time.format.DateTimeFormatter @@ -66,8 +70,9 @@ publishing { pom { name.set("webrtc-java") - description.set("Java native interface implementation based on the free, open WebRTC project.") + description.set("A JNI implementation WebRTC for data channels.") url.set("https://github.com/Kas-tle/webrtc-java") + inceptionYear.set("2025") licenses { license { name.set("The Apache Software License, Version 2.0") @@ -85,23 +90,33 @@ publishing { connection.set("scm:git:git://github.com/Kas-tle/webrtc-java.git") url.set("https://github.com/Kas-tle/webrtc-java") } + ciManagement { + system.set("GitHub Actions") + url.set("https://github.com/Kas-tle/webrtc-java/actions") + } + issueManagement { + system.set("GitHub Issues") + url.set("https://github.com/Kas-tle/webrtc-java/issues") + } } // These jars are downloaded by the GitHub Actions "Publish" job into a folder - val nativeLibsDir = project.findProperty("nativeLibsDir") as? String - if (nativeLibsDir != null) { - val dir = file(nativeLibsDir) - if (dir.exists()) { - dir.listFiles()?.filter { it.name.endsWith(".jar") && it.name.contains("webrtc-java") }?.forEach { jarFile -> - // Don't re-attach the main jar - if (!jarFile.name.equals("webrtc-java-${version}.jar") && !jarFile.name.contains("-sources") && !jarFile.name.contains("-javadoc")) { - artifact(jarFile) { - // Extract classifier from filename: webrtc-java-0.15.0-linux-x86_64.jar -> linux-x86_64 - val classifierStr = jarFile.name - .replace("webrtc-java-${version}-", "") - .replace(".jar", "") - classifier = classifierStr - } + val nativeStagingdir = file(rootProject.projectDir.resolve("native-staging")) + if (nativeStagingdir.exists()) { + logger.lifecycle("Attaching native jars from: ${nativeStagingdir.absolutePath}") + // list files in dir and subdirs + val nativeFiles: Sequence = nativeStagingdir.walkTopDown() + + nativeFiles.filter { it.name.endsWith(".jar") && it.name.contains("webrtc-java") }.forEach { jarFile -> + // Don't re-attach the main jar + if (!jarFile.name.equals("webrtc-java-${version}.jar") && !jarFile.name.contains("-sources") && !jarFile.name.contains("-javadoc")) { + artifact(jarFile) { + // Extract classifier from filename: webrtc-java-0.15.0-linux-x86_64.jar -> linux-x86_64 + val classifierStr = jarFile.name + .replace("webrtc-java-${version}-", "") + .replace(".jar", "") + classifier = classifierStr + logger.lifecycle("Attached native jar: ${jarFile.name} with classifier: ${classifierStr}") } } } @@ -111,7 +126,7 @@ publishing { } signing { - if (System.getenv("PGP_SECRET") != null) { + if (System.getenv("PGP_SECRET") != null && System.getenv("PGP_PASSPHRASE") != null) { useInMemoryPgpKeys(System.getenv("PGP_SECRET"), System.getenv("PGP_PASSPHRASE")) sign(publishing.publications["maven"]) } From 95a5e61da590f3bb70b5041835491b1db5e3d22b Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Fri, 26 Dec 2025 17:28:29 -0800 Subject: [PATCH 75/81] Add foojay-resolver-convention for jdk toolchain download Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- settings.gradle.kts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/settings.gradle.kts b/settings.gradle.kts index c153b45..2da6343 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -5,6 +5,10 @@ pluginManagement { } } +plugins { + id("org.gradle.toolchains.foojay-resolver-convention") version ("1.0.0") +} + rootProject.name = "webrtc-java-parent" include("webrtc-jni") From 1a3aa089c6aa7fca662438624aac0b857b2c148d Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Fri, 26 Dec 2025 22:25:52 -0800 Subject: [PATCH 76/81] Modify action layout Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/build/action.yml | 15 -- .github/actions/checkout/action.yml | 18 ++ .github/actions/download-artifact/action.yml | 23 +++ .github/actions/publish/actions.yml | 14 ++ .github/actions/setup-gradle/action.yml | 38 +++++ .github/actions/test/action.yml | 34 +--- .github/workflows/build.yml | 164 +++++++++++-------- README.md | 2 +- 8 files changed, 192 insertions(+), 116 deletions(-) create mode 100644 .github/actions/checkout/action.yml create mode 100644 .github/actions/download-artifact/action.yml create mode 100644 .github/actions/publish/actions.yml create mode 100644 .github/actions/setup-gradle/action.yml diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index 71e4188..0dba4e1 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -3,11 +3,6 @@ name: "Gradle Build" description: "Build the platform dependent Java library" inputs: - java-version: - description: "The Java build version." - required: true - default: "17" - platform-name: description: "The target platform." required: true @@ -27,16 +22,6 @@ runs: with: path: ${{ env.WEBRTC_CHECKOUT_FOLDER }}/build key: webrtc-${{ hashFiles('webrtc-jni/gradle.properties') }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt') }} - restore-keys: webrtc-${{ hashFiles('webrtc-jni/gradle.properties') }}-${{ inputs.platform-name }}- - - - uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e - # https://github.com/actions/setup-java/releases/latest - with: - distribution: "liberica" - java-version: ${{ inputs.java-version }} - - - uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 - # https://github.com/gradle/actions/releases/latest - name: Build env: diff --git a/.github/actions/checkout/action.yml b/.github/actions/checkout/action.yml new file mode 100644 index 0000000..5999388 --- /dev/null +++ b/.github/actions/checkout/action.yml @@ -0,0 +1,18 @@ +name: "Checkout Code" + +description: "Checkout the repository code" + +inputs: + fetch-depth: + description: "The depth of the fetch during checkout." + required: false + default: "1" + +runs: + using: "composite" + steps: + - name: Checkout code + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 + # https://github.com/actions/checkout/releases/latest + with: + fetch-depth: ${{ inputs.fetch-depth }} \ No newline at end of file diff --git a/.github/actions/download-artifact/action.yml b/.github/actions/download-artifact/action.yml new file mode 100644 index 0000000..c9c87cc --- /dev/null +++ b/.github/actions/download-artifact/action.yml @@ -0,0 +1,23 @@ +name: "Download Artifacts" + +description: "Downloads the specified artifacts" + +inputs: + name: + description: "The name of the artifact to download." + required: false + default: "" + path: + description: "The path to download the artifact to." + required: false + default: "" + +runs: + using: "composite" + steps: + - name: Download Artifacts + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 + # https://github.com/actions/download-artifact/releases/latest + with: + name: ${{ inputs.name }} + path: ${{ inputs.path }} diff --git a/.github/actions/publish/actions.yml b/.github/actions/publish/actions.yml new file mode 100644 index 0000000..976fb6a --- /dev/null +++ b/.github/actions/publish/actions.yml @@ -0,0 +1,14 @@ +name: "Gradle Publish" + +description: "Publish the library to Maven Central" + +runs: + using: "composite" + steps: + - uses: ./github/actions/download-artifact + with: + path: native-staging + + - name: Publish + run: ./gradlew publishAggregationToCentralPortal + shell: bash diff --git a/.github/actions/setup-gradle/action.yml b/.github/actions/setup-gradle/action.yml new file mode 100644 index 0000000..e3016a1 --- /dev/null +++ b/.github/actions/setup-gradle/action.yml @@ -0,0 +1,38 @@ +name: "Setup Gradle" + +description: "Sets up Gradle and Java for use in actions" + +inputs: + java-architecture: + description: "The target architecture." + required: false + default: "" + + gradle-cache-read-only: + description: "Whether to set up Gradle cache in read-only mode." + required: false + default: "true" + +runs: + using: "composite" + steps: + - name: Install 32-bit ARM libraries + if: inputs.java-architecture == 'armv7' + run: | + sudo dpkg --add-architecture armhf + sudo apt-get update + sudo apt-get install -y libc6:armhf libstdc++6:armhf zlib1g:armhf + shell: bash + + - uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e + # https://github.com/actions/setup-java/releases/latest + with: + distribution: "liberica" + java-version: "17" + architecture: ${{ inputs.java-architecture }} + + - uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 + # https://github.com/gradle/actions/releases/latest + with: + cache-read-only: ${{ inputs.gradle-cache-read-only }} + diff --git a/.github/actions/test/action.yml b/.github/actions/test/action.yml index 2dcbd5d..4817092 100644 --- a/.github/actions/test/action.yml +++ b/.github/actions/test/action.yml @@ -3,46 +3,14 @@ name: "Gradle Test" description: "Test the platform dependent Java library" inputs: - java-version: - description: "The Java build version." - required: true - default: "17" - platform-name: description: "The target platform." required: true - architecture: - description: "The target architecture." - required: false - default: "" - runs: using: "composite" steps: - - name: Install 32-bit ARM libraries - if: inputs.architecture == 'armv7' - run: | - sudo dpkg --add-architecture armhf - sudo apt-get update - sudo apt-get install -y libc6:armhf libstdc++6:armhf zlib1g:armhf - shell: bash - - - uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e - # https://github.com/actions/setup-java/releases/latest - with: - distribution: "liberica" - java-version: ${{ inputs.java-version }} - architecture: ${{ inputs.architecture }} - - - uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 - # https://github.com/gradle/actions/releases/latest - with: - cache-read-only: true - - - name: Download JNI Artifact - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 - # https://github.com/actions/download-artifact/releases/latest + - uses: ./github/actions/download-artifact with: name: webrtc-java-jni-${{ inputs.platform-name }} path: artifacts diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a685079..84905b4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,22 +24,15 @@ jobs: runs-on: windows-2022 - name: windows-aarch64 runs-on: windows-2022 - java: [17] runs-on: ${{ matrix.platform.runs-on }} steps: - - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 - # https://github.com/actions/checkout/releases/latest - - - id: prepare - name: Prepare build - uses: ./.github/actions/prepare-windows - - - id: gradle-build - name: Gradle build - uses: ./.github/actions/build + - uses: ./github/actions/checkout + - uses: ./.github/actions/prepare-windows + - uses: ./.github/actions/setup-gradle + with: + gradle-cache-read-only: "false" + - uses: ./.github/actions/build with: - java-version: ${{ matrix.java }} platform-name: ${{ matrix.platform.name }} test-windows: @@ -57,18 +50,12 @@ jobs: - name: windows-11-arm_windows-aarch64 artifact-name: windows-aarch64 runs-on: windows-11-arm - java: [17] runs-on: ${{ matrix.platform.runs-on }} steps: - - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 - # https://github.com/actions/checkout/releases/latest - - - id: gradle-test - name: Gradle test - uses: ./.github/actions/test + - uses: ./github/actions/checkout + - uses: ./.github/actions/setup-gradle + - uses: ./.github/actions/test with: - java-version: ${{ matrix.java }} platform-name: ${{ matrix.platform.artifact-name }} build-linux: @@ -82,22 +69,15 @@ jobs: runs-on: ubuntu-22.04 - name: linux-x86_64 runs-on: ubuntu-22.04 - java: [17] runs-on: ${{ matrix.platform.runs-on }} steps: - - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 - # https://github.com/actions/checkout/releases/latest - - - id: prepare - name: Prepare build - uses: ./.github/actions/prepare-linux - - - id: gradle-build - name: Gradle build - uses: ./.github/actions/build + - uses: ./github/actions/checkout + - uses: ./.github/actions/prepare-linux + - uses: ./.github/actions/setup-gradle + with: + gradle-cache-read-only: "false" + - uses: ./.github/actions/build with: - java-version: ${{ matrix.java }} platform-name: ${{ matrix.platform.name }} test-linux: @@ -130,20 +110,15 @@ jobs: artifact-name: linux-x86_64 runs-on: ubuntu-24.04 java-arch: x64 - java: [17] runs-on: ${{ matrix.platform.runs-on }} steps: - - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 - # https://github.com/actions/checkout/releases/latest - - - id: gradle-test - name: Gradle test - uses: ./.github/actions/test + - uses: ./github/actions/checkout + - uses: ./.github/actions/setup-gradle + with: + java-architecture: ${{ matrix.platform.java-arch }} + - uses: ./.github/actions/test with: - java-version: ${{ matrix.java }} platform-name: ${{ matrix.platform.artifact-name }} - architecture: ${{ matrix.platform.java-arch }} build-macos: strategy: @@ -154,22 +129,15 @@ jobs: runs-on: macos-14 - name: macos-aarch64 runs-on: macos-14 - java: [17] runs-on: ${{ matrix.platform.runs-on }} steps: - - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 - # https://github.com/actions/checkout/releases/latest - - - id: prepare-build - name: Prepare build - uses: ./.github/actions/prepare-macos - - - id: gradle-build - name: Gradle build - uses: ./.github/actions/build + - uses: ./github/actions/checkout + - uses: ./.github/actions/prepare-macos + - uses: ./.github/actions/setup-gradle + with: + gradle-cache-read-only: "false" + - uses: ./.github/actions/build with: - java-version: ${{ matrix.java }} platform-name: ${{ matrix.platform.name }} test-macos: @@ -190,17 +158,79 @@ jobs: - name: macos-26_macos-aarch64 artifact-name: macos-aarch64 runs-on: macos-26 - java: [17] runs-on: ${{ matrix.platform.runs-on }} steps: - - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 - # https://github.com/actions/checkout/releases/latest - - - id: gradle-test - name: Gradle test - uses: ./.github/actions/test + - uses: ./github/actions/checkout + - uses: ./.github/actions/setup-gradle + - uses: ./.github/actions/test with: - java-version: ${{ matrix.java }} platform-name: ${{ matrix.platform.artifact-name }} + detect-release: + needs: + - test-windows + - test-linux + - test-macos + if: ${{ success() && github.repository == 'Kas-tle/webrtc-java' && github.ref_name == 'master' }} + runs-on: ubuntu-22.04 + outputs: + unreleased: ${{ steps.version.outputs.unreleased }} + version: ${{ steps.version.outputs.version }} + steps: + - uses: ./github/actions/checkout + with: + fetch-depth: "0" + - name: Get Version + id: version + run: | + version=$(cat gradle.properties | grep version= | cut -d'=' -f2) + echo "version=$version" >> $GITHUB_OUTPUT + unreleased=$(git show-ref --tags --verify --quiet "refs/tags/${version}" && echo false || echo true) + echo "unreleased=$unreleased" >> $GITHUB_OUTPUT + shell: bash + + release: + needs: + - detect-release + if: ${{ success() && github.repository == 'Kas-tle/webrtc-java' && github.ref_name == 'master' && needs.detect-release.outputs.unreleased == 'true' }} + runs-on: ubuntu-22.04 + outputs: + release_id: ${{ steps.release.outputs.releaseID }} + steps: + - uses: ./github/actions/checkout + - uses: ./.github/actions/setup-gradle + - uses: ./.github/actions/publish + env: + MAVEN_CENTRAL_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} + MAVEN_CENTRAL_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }} + PGP_SECRET: ${{ secrets.PGP_SECRET }} + PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} + - name: Make Release Publication + id: release + uses: Kas-tle/base-release-action@65d06f835be34757c6d73c16959c97e92c2a3c7f + with: + files: | + webrtc/build/libs/*.jar + native-staging/**/*.jar + appID: ${{ secrets.RELEASE_APP_ID }} + appPrivateKey: ${{ secrets.RELEASE_APP_PK }} + discordWebhook: ${{ secrets.DISCORD_WEBHOOK }} + tagBase: ${{ needs.detect-release.outputs.version }} + tagIncrement: false + tagSeparator: "" + tagPrefix: "" + releaseName: ${{ needs.detect-release.outputs.version }} + releaseBodyDependencyUsage: "java" + releaseBodyDependencyJavaGroupId: "dev.kastle.webrtc" + releaseBodyDependencyJavaArtifactId: "webrtc-java" + + upload-logs: + name: Upload Logs + runs-on: ubuntu-22.04 + needs: release + if: ${{ success() && github.repository == 'Kas-tle/webrtc-java' && github.ref_name == 'master' }} + steps: + - uses: Kas-tle/release-build-log-action@1b57448eaf9476e6e05450e4ea240449eac2c0d2 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + releaseID: ${{ needs.release.outputs.release_id }} diff --git a/README.md b/README.md index 108270b..98762cc 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Note that the natives are not bundled with the main library, so you will need to The project has a preconfigured `.vscode` setup for easy development. Make sure to install the recommended extensions when prompted. Run the `./gradlew build` command to build the project. Note that building the native libraries requires [clang](https://clang.llvm.org/get_started.html) and [cmake](https://cmake.org/download/) to be installed and on your path. -The initial build will take significant time to compile, as cloning the WebRTC source code brings in multiple other repo source trees from the Chromium project, requiring about 20 GB of disk space. On Windows, you may need to set `WEBRTC_CHECKOUT_FOLDER` to a shorter path to avoid exceeding file path length limits. +The initial build will take significant time to compile, as cloning the WebRTC source code brings in multiple other repo source trees from the Chromium project, requiring about 30 GB of disk space. On Windows, you may need to set `WEBRTC_CHECKOUT_FOLDER` to a shorter path to avoid exceeding file path length limits. The version of WebRTC used can be changed by modifying the `webrtc.branch` property in [`webrtc-jni/gradle.properties`](webrtc-jni/gradle.properties). Note, however, that changing the version used will likely require updating the patches in [`webrtc-jni/src/main/cpp/dependencies/webrtc/patches/`](webrtc-jni/src/main/cpp/dependencies/webrtc/patches/) to ensure successful compilation. From 630e12d93a02a88cef069a982daa9c46b40de98c Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Fri, 26 Dec 2025 22:28:50 -0800 Subject: [PATCH 77/81] Fix paths Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/publish/actions.yml | 2 +- .github/actions/test/action.yml | 2 +- .github/workflows/build.yml | 16 ++++++++-------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/actions/publish/actions.yml b/.github/actions/publish/actions.yml index 976fb6a..c922b67 100644 --- a/.github/actions/publish/actions.yml +++ b/.github/actions/publish/actions.yml @@ -5,7 +5,7 @@ description: "Publish the library to Maven Central" runs: using: "composite" steps: - - uses: ./github/actions/download-artifact + - uses: ./.github/actions/download-artifact with: path: native-staging diff --git a/.github/actions/test/action.yml b/.github/actions/test/action.yml index 4817092..39b928a 100644 --- a/.github/actions/test/action.yml +++ b/.github/actions/test/action.yml @@ -10,7 +10,7 @@ inputs: runs: using: "composite" steps: - - uses: ./github/actions/download-artifact + - uses: ./.github/actions/download-artifact with: name: webrtc-java-jni-${{ inputs.platform-name }} path: artifacts diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 84905b4..e4b534a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,7 +26,7 @@ jobs: runs-on: windows-2022 runs-on: ${{ matrix.platform.runs-on }} steps: - - uses: ./github/actions/checkout + - uses: ./.github/actions/checkout - uses: ./.github/actions/prepare-windows - uses: ./.github/actions/setup-gradle with: @@ -52,7 +52,7 @@ jobs: runs-on: windows-11-arm runs-on: ${{ matrix.platform.runs-on }} steps: - - uses: ./github/actions/checkout + - uses: ./.github/actions/checkout - uses: ./.github/actions/setup-gradle - uses: ./.github/actions/test with: @@ -71,7 +71,7 @@ jobs: runs-on: ubuntu-22.04 runs-on: ${{ matrix.platform.runs-on }} steps: - - uses: ./github/actions/checkout + - uses: ./.github/actions/checkout - uses: ./.github/actions/prepare-linux - uses: ./.github/actions/setup-gradle with: @@ -112,7 +112,7 @@ jobs: java-arch: x64 runs-on: ${{ matrix.platform.runs-on }} steps: - - uses: ./github/actions/checkout + - uses: ./.github/actions/checkout - uses: ./.github/actions/setup-gradle with: java-architecture: ${{ matrix.platform.java-arch }} @@ -131,7 +131,7 @@ jobs: runs-on: macos-14 runs-on: ${{ matrix.platform.runs-on }} steps: - - uses: ./github/actions/checkout + - uses: ./.github/actions/checkout - uses: ./.github/actions/prepare-macos - uses: ./.github/actions/setup-gradle with: @@ -160,7 +160,7 @@ jobs: runs-on: macos-26 runs-on: ${{ matrix.platform.runs-on }} steps: - - uses: ./github/actions/checkout + - uses: ./.github/actions/checkout - uses: ./.github/actions/setup-gradle - uses: ./.github/actions/test with: @@ -177,7 +177,7 @@ jobs: unreleased: ${{ steps.version.outputs.unreleased }} version: ${{ steps.version.outputs.version }} steps: - - uses: ./github/actions/checkout + - uses: ./.github/actions/checkout with: fetch-depth: "0" - name: Get Version @@ -197,7 +197,7 @@ jobs: outputs: release_id: ${{ steps.release.outputs.releaseID }} steps: - - uses: ./github/actions/checkout + - uses: ./.github/actions/checkout - uses: ./.github/actions/setup-gradle - uses: ./.github/actions/publish env: From de08213268fa28866e91ea41f8bba50098ebe94e Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Fri, 26 Dec 2025 22:44:46 -0800 Subject: [PATCH 78/81] Store checkout action elsewhere Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/checkout/action.yml | 18 ------------------ .github/workflows/build.yml | 16 ++++++++-------- 2 files changed, 8 insertions(+), 26 deletions(-) delete mode 100644 .github/actions/checkout/action.yml diff --git a/.github/actions/checkout/action.yml b/.github/actions/checkout/action.yml deleted file mode 100644 index 5999388..0000000 --- a/.github/actions/checkout/action.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: "Checkout Code" - -description: "Checkout the repository code" - -inputs: - fetch-depth: - description: "The depth of the fetch during checkout." - required: false - default: "1" - -runs: - using: "composite" - steps: - - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 - # https://github.com/actions/checkout/releases/latest - with: - fetch-depth: ${{ inputs.fetch-depth }} \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e4b534a..a1d8312 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,7 +26,7 @@ jobs: runs-on: windows-2022 runs-on: ${{ matrix.platform.runs-on }} steps: - - uses: ./.github/actions/checkout + - uses: Kas-tle/actions/checkout@main - uses: ./.github/actions/prepare-windows - uses: ./.github/actions/setup-gradle with: @@ -52,7 +52,7 @@ jobs: runs-on: windows-11-arm runs-on: ${{ matrix.platform.runs-on }} steps: - - uses: ./.github/actions/checkout + - uses: Kas-tle/actions/checkout@main - uses: ./.github/actions/setup-gradle - uses: ./.github/actions/test with: @@ -71,7 +71,7 @@ jobs: runs-on: ubuntu-22.04 runs-on: ${{ matrix.platform.runs-on }} steps: - - uses: ./.github/actions/checkout + - uses: Kas-tle/actions/checkout@main - uses: ./.github/actions/prepare-linux - uses: ./.github/actions/setup-gradle with: @@ -112,7 +112,7 @@ jobs: java-arch: x64 runs-on: ${{ matrix.platform.runs-on }} steps: - - uses: ./.github/actions/checkout + - uses: Kas-tle/actions/checkout@main - uses: ./.github/actions/setup-gradle with: java-architecture: ${{ matrix.platform.java-arch }} @@ -131,7 +131,7 @@ jobs: runs-on: macos-14 runs-on: ${{ matrix.platform.runs-on }} steps: - - uses: ./.github/actions/checkout + - uses: Kas-tle/actions/checkout@main - uses: ./.github/actions/prepare-macos - uses: ./.github/actions/setup-gradle with: @@ -160,7 +160,7 @@ jobs: runs-on: macos-26 runs-on: ${{ matrix.platform.runs-on }} steps: - - uses: ./.github/actions/checkout + - uses: Kas-tle/actions/checkout@main - uses: ./.github/actions/setup-gradle - uses: ./.github/actions/test with: @@ -177,7 +177,7 @@ jobs: unreleased: ${{ steps.version.outputs.unreleased }} version: ${{ steps.version.outputs.version }} steps: - - uses: ./.github/actions/checkout + - uses: Kas-tle/actions/checkout@main with: fetch-depth: "0" - name: Get Version @@ -197,7 +197,7 @@ jobs: outputs: release_id: ${{ steps.release.outputs.releaseID }} steps: - - uses: ./.github/actions/checkout + - uses: Kas-tle/actions/checkout@main - uses: ./.github/actions/setup-gradle - uses: ./.github/actions/publish env: From d1722c609359bbab23005d575fc4e808cc73a39e Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Fri, 26 Dec 2025 22:57:59 -0800 Subject: [PATCH 79/81] Name steps Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/workflows/build.yml | 40 ++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a1d8312..4a52b05 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,6 +16,7 @@ on: jobs: build-windows: + name: Build Windows strategy: fail-fast: false matrix: @@ -27,15 +28,20 @@ jobs: runs-on: ${{ matrix.platform.runs-on }} steps: - uses: Kas-tle/actions/checkout@main + name: Checkout Repository - uses: ./.github/actions/prepare-windows + name: Prepare Windows - uses: ./.github/actions/setup-gradle with: gradle-cache-read-only: "false" + name: Setup Gradle - uses: ./.github/actions/build with: platform-name: ${{ matrix.platform.name }} + name: Build test-windows: + name: Test Windows needs: build-windows strategy: fail-fast: false @@ -53,12 +59,16 @@ jobs: runs-on: ${{ matrix.platform.runs-on }} steps: - uses: Kas-tle/actions/checkout@main + name: Checkout Repository - uses: ./.github/actions/setup-gradle + name: Setup Gradle - uses: ./.github/actions/test with: platform-name: ${{ matrix.platform.artifact-name }} + name: Test build-linux: + name: Build Linux strategy: fail-fast: false matrix: @@ -72,15 +82,20 @@ jobs: runs-on: ${{ matrix.platform.runs-on }} steps: - uses: Kas-tle/actions/checkout@main + name: Checkout Repository - uses: ./.github/actions/prepare-linux + name: Prepare Linux - uses: ./.github/actions/setup-gradle with: gradle-cache-read-only: "false" + name: Setup Gradle - uses: ./.github/actions/build with: platform-name: ${{ matrix.platform.name }} + name: Build test-linux: + name: Test Linux needs: build-linux strategy: fail-fast: false @@ -113,14 +128,18 @@ jobs: runs-on: ${{ matrix.platform.runs-on }} steps: - uses: Kas-tle/actions/checkout@main + name: Checkout Repository - uses: ./.github/actions/setup-gradle with: java-architecture: ${{ matrix.platform.java-arch }} + name: Setup Gradle - uses: ./.github/actions/test with: platform-name: ${{ matrix.platform.artifact-name }} + name: Test build-macos: + name: Build macOS strategy: fail-fast: false matrix: @@ -132,15 +151,20 @@ jobs: runs-on: ${{ matrix.platform.runs-on }} steps: - uses: Kas-tle/actions/checkout@main + name: Checkout Repository - uses: ./.github/actions/prepare-macos + name: Prepare macOS - uses: ./.github/actions/setup-gradle with: gradle-cache-read-only: "false" + name: Setup Gradle - uses: ./.github/actions/build with: platform-name: ${{ matrix.platform.name }} + name: Build test-macos: + name: Test macOS needs: build-macos strategy: fail-fast: false @@ -161,12 +185,16 @@ jobs: runs-on: ${{ matrix.platform.runs-on }} steps: - uses: Kas-tle/actions/checkout@main + name: Checkout Repository - uses: ./.github/actions/setup-gradle + name: Setup Gradle - uses: ./.github/actions/test with: platform-name: ${{ matrix.platform.artifact-name }} + name: Test detect-release: + name: Detect Release needs: - test-windows - test-linux @@ -180,7 +208,8 @@ jobs: - uses: Kas-tle/actions/checkout@main with: fetch-depth: "0" - - name: Get Version + name: Checkout Repository + - name: Get Release Version id: version run: | version=$(cat gradle.properties | grep version= | cut -d'=' -f2) @@ -190,6 +219,7 @@ jobs: shell: bash release: + name: Release and Publish needs: - detect-release if: ${{ success() && github.repository == 'Kas-tle/webrtc-java' && github.ref_name == 'master' && needs.detect-release.outputs.unreleased == 'true' }} @@ -198,16 +228,18 @@ jobs: release_id: ${{ steps.release.outputs.releaseID }} steps: - uses: Kas-tle/actions/checkout@main + name: Checkout Repository - uses: ./.github/actions/setup-gradle + name: Setup Gradle - uses: ./.github/actions/publish env: MAVEN_CENTRAL_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} MAVEN_CENTRAL_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }} PGP_SECRET: ${{ secrets.PGP_SECRET }} PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} - - name: Make Release Publication + name: Publish to Maven Central + - uses: Kas-tle/base-release-action@65d06f835be34757c6d73c16959c97e92c2a3c7f id: release - uses: Kas-tle/base-release-action@65d06f835be34757c6d73c16959c97e92c2a3c7f with: files: | webrtc/build/libs/*.jar @@ -223,6 +255,7 @@ jobs: releaseBodyDependencyUsage: "java" releaseBodyDependencyJavaGroupId: "dev.kastle.webrtc" releaseBodyDependencyJavaArtifactId: "webrtc-java" + name: Create Release upload-logs: name: Upload Logs @@ -234,3 +267,4 @@ jobs: with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} releaseID: ${{ needs.release.outputs.release_id }} + name: Upload Build Logs to Release From 86397f4576c0731300230e1526751750b21a35b5 Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Sat, 27 Dec 2025 18:12:58 -0800 Subject: [PATCH 80/81] Build should be faster Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .../cpp/dependencies/webrtc/CMakeLists.txt | 40 ++++++++----------- .../webrtc/patches/linux/.gitkeep | 0 .../patches/linux/stack_copier_signal.patch | 10 ----- .../webrtc/patches/macos/.gitkeep | 0 .../webrtc/patches/windows/.gitkeep | 0 5 files changed, 17 insertions(+), 33 deletions(-) create mode 100644 webrtc-jni/src/main/cpp/dependencies/webrtc/patches/linux/.gitkeep delete mode 100644 webrtc-jni/src/main/cpp/dependencies/webrtc/patches/linux/stack_copier_signal.patch create mode 100644 webrtc-jni/src/main/cpp/dependencies/webrtc/patches/macos/.gitkeep create mode 100644 webrtc-jni/src/main/cpp/dependencies/webrtc/patches/windows/.gitkeep diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt index 23e5b25..567a1c2 100644 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt @@ -193,52 +193,47 @@ set(ENV{PATH} "${WEBRTC_SRC_DIR}/depot_tools${PATH_SEP}$ENV{PATH}") file(MAKE_DIRECTORY ${WEBRTC_DIR}) -message(STATUS "WebRTC: fetch") +message(STATUS "WebRTC: Configuring gclient for branch ${WEBRTC_BRANCH}") + execute_command( - COMMAND fetch --nohooks --no-history webrtc + COMMAND gclient config --name src --unmanaged "https://webrtc.googlesource.com/src.git@${WEBRTC_BRANCH}" WORKING_DIRECTORY "${WEBRTC_DIR}" ) -message(STATUS "WebRTC: checkout \"${WEBRTC_BRANCH}\"") -execute_command( - COMMAND git checkout . - WORKING_DIRECTORY "${WEBRTC_SRC}" -) +if(APPLE) + set(WEBRTC_TARGET_OS "['mac']") +elseif(WIN32) + set(WEBRTC_TARGET_OS "['win']") +else() + set(WEBRTC_TARGET_OS "['linux']") +endif() -message(STATUS "WebRTC: fetching specific branch ${WEBRTC_BRANCH}") -execute_command( - COMMAND git fetch origin ${WEBRTC_BRANCH}:${WEBRTC_BRANCH} - WORKING_DIRECTORY "${WEBRTC_SRC}" -) +file(APPEND "${WEBRTC_DIR}/.gclient" "target_os = ${WEBRTC_TARGET_OS}\n") -message(STATUS "WebRTC: checkout to ${WEBRTC_BRANCH}") +message(STATUS "WebRTC: Syncing Sources (No Hooks, Shallow)") execute_command( - COMMAND git checkout ${WEBRTC_BRANCH} - WORKING_DIRECTORY "${WEBRTC_SRC}" + COMMAND gclient sync -D --no-history --nohooks -j16 + WORKING_DIRECTORY "${WEBRTC_DIR}" ) -message(STATUS "WebRTC: Patching DEPS to skip download of test resources") +message(STATUS "WebRTC: Patching DEPS") set(DEPS_FILE "${WEBRTC_SRC}/DEPS") - if(EXISTS "${DEPS_FILE}") file(READ "${DEPS_FILE}" DEPS_CONTENT) - string(REPLACE "'src/resources']," "'src/resources'], 'condition': 'False'," DEPS_CONTENT "${DEPS_CONTENT}" ) - file(WRITE "${DEPS_FILE}" "${DEPS_CONTENT}") else() message(WARNING "WebRTC: DEPS file not found. Optimization skipped.") endif() - -message(STATUS "WebRTC: sync") +message(STATUS "WebRTC: Final Sync (Artifacts)") execute_command( - COMMAND gclient sync -D --no-history -j8 + COMMAND gclient sync -D --no-history -j16 WORKING_DIRECTORY "${WEBRTC_DIR}" ) @@ -299,7 +294,6 @@ rtc_enable_protobuf=false \ rtc_include_tests=false \ rtc_include_dav1d_in_internal_decoder_factory=false \ rtc_enable_google_benchmarks=false \ -rtc_video_psnr=false \ use_rtti=true \ symbol_level=0 \ use_dbus=false \ diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/patches/linux/.gitkeep b/webrtc-jni/src/main/cpp/dependencies/webrtc/patches/linux/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/patches/linux/stack_copier_signal.patch b/webrtc-jni/src/main/cpp/dependencies/webrtc/patches/linux/stack_copier_signal.patch deleted file mode 100644 index 0a008cf..0000000 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/patches/linux/stack_copier_signal.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- src/base/profiler/stack_copier_signal.cc 2020-12-16 18:39:43.284026104 +0100 -+++ src/base/profiler/stack_copier_signal_new.cc 2020-12-16 18:39:58.256359806 +0100 -@@ -6,6 +6,7 @@ - - #include - #include -+#include - #include - #include - diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/patches/macos/.gitkeep b/webrtc-jni/src/main/cpp/dependencies/webrtc/patches/macos/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/patches/windows/.gitkeep b/webrtc-jni/src/main/cpp/dependencies/webrtc/patches/windows/.gitkeep new file mode 100644 index 0000000..e69de29 From e6b9961fce078c728a0123c4d2d68b4076c3b3d9 Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Sat, 27 Dec 2025 20:15:57 -0800 Subject: [PATCH 81/81] Restructure build and webrtc cache Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .github/actions/build/action.yml | 39 ++++++- .github/actions/prepare-linux/action.yml | 11 +- .github/actions/test/action.yml | 5 +- .github/workflows/build.yml | 109 ++++++++++-------- webrtc-jni/build.gradle.kts | 13 +-- ...-linux-clang.cmake => linux-aarch32.cmake} | 0 ...-linux-clang.cmake => linux-aarch64.cmake} | 0 ...4-linux-clang.cmake => linux-x86_64.cmake} | 0 ...-macos-clang.cmake => macos-aarch64.cmake} | 0 ...4-macos-cross.cmake => macos-x86_64.cmake} | 0 ...dows-clang.cmake => windows-aarch64.cmake} | 0 ...ndows-clang.cmake => windows-x86_64.cmake} | 0 webrtc/build.gradle.kts | 4 +- 13 files changed, 110 insertions(+), 71 deletions(-) rename webrtc-jni/src/main/cpp/toolchain/{aarch32-linux-clang.cmake => linux-aarch32.cmake} (100%) rename webrtc-jni/src/main/cpp/toolchain/{aarch64-linux-clang.cmake => linux-aarch64.cmake} (100%) rename webrtc-jni/src/main/cpp/toolchain/{x86_64-linux-clang.cmake => linux-x86_64.cmake} (100%) rename webrtc-jni/src/main/cpp/toolchain/{aarch64-macos-clang.cmake => macos-aarch64.cmake} (100%) rename webrtc-jni/src/main/cpp/toolchain/{x86_64-macos-cross.cmake => macos-x86_64.cmake} (100%) rename webrtc-jni/src/main/cpp/toolchain/{aarch64-windows-clang.cmake => windows-aarch64.cmake} (100%) rename webrtc-jni/src/main/cpp/toolchain/{x86_64-windows-clang.cmake => windows-x86_64.cmake} (100%) diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index 0dba4e1..dd63d8e 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -6,6 +6,9 @@ inputs: platform-name: description: "The target platform." required: true + platform-arch: + description: "The target platform architecture." + required: true runs: using: "composite" @@ -16,16 +19,24 @@ runs: echo "WEBRTC_CHECKOUT_FOLDER=~/webrtc" >> $GITHUB_ENV shell: bash - - name: Set up WebRTC cache - uses: actions/cache@6f8efc29b200d32929f49075959781ed54ec270c + - name: Restore WebRTC cache + uses: actions/cache/restore@6f8efc29b200d32929f49075959781ed54ec270c # https://github.com/actions/cache/releases/latest with: path: ${{ env.WEBRTC_CHECKOUT_FOLDER }}/build - key: webrtc-${{ hashFiles('webrtc-jni/gradle.properties') }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt') }} + key: >- + webrtc-${{ hashFiles('webrtc-jni/gradle.properties') }}-${{ inputs.platform-name }}-${{ inputs.platform-arch }}-${{ + hashFiles( + 'webrtc-jni/src/main/cpp/CMakeLists.txt', + 'webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt', + format('webrtc-jni/src/main/cpp/dependencies/webrtc/patches/{0}/*.patch', inputs.platform-name), + format('webrtc-jni/src/main/cpp/toolchain/{0}-{1}.cmake', inputs.platform-name, inputs.platform-arch) + ) + }} - name: Build env: - WEBRTC_PLATFORM: ${{ inputs.platform-name }} + WEBRTC_PLATFORM: ${{ inputs.platform-name }}-${{ inputs.platform-arch }} run: ./gradlew build -x test shell: bash @@ -33,12 +44,28 @@ runs: uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # https://github.com/actions/upload-artifact/releases/latest with: - name: webrtc-java-${{ inputs.platform-name }} + name: webrtc-java-${{ inputs.platform-name }}-${{ inputs.platform-arch }} path: webrtc/build/libs/*.jar - name: Archive webrtc-java-jni uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # https://github.com/actions/upload-artifact/releases/latest with: - name: webrtc-java-jni-${{ inputs.platform-name }} + name: webrtc-java-jni-${{ inputs.platform-name }}-${{ inputs.platform-arch }} path: webrtc-jni/build/libs/*.jar + + - name: Save WebRTC cache + uses: actions/cache/save@6f8efc29b200d32929f49075959781ed54ec270c + # https://github.com/actions/cache/releases/latest + if: ${{ github.event_name != 'pull_request' }} + with: + path: ${{ env.WEBRTC_CHECKOUT_FOLDER }}/build + key: >- + webrtc-${{ hashFiles('webrtc-jni/gradle.properties') }}-${{ inputs.platform-name }}-${{ inputs.platform-arch }}-${{ + hashFiles( + 'webrtc-jni/src/main/cpp/CMakeLists.txt', + 'webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt', + format('webrtc-jni/src/main/cpp/dependencies/webrtc/patches/{0}/*.patch', inputs.platform-name), + format('webrtc-jni/src/main/cpp/toolchain/{0}-{1}.cmake', inputs.platform-name, inputs.platform-arch) + ) + }} diff --git a/.github/actions/prepare-linux/action.yml b/.github/actions/prepare-linux/action.yml index 85111ac..17efecb 100644 --- a/.github/actions/prepare-linux/action.yml +++ b/.github/actions/prepare-linux/action.yml @@ -2,6 +2,11 @@ name: "Prepare Linux Build" description: "Frees up disk space and installs required packages for Linux builds." +inputs: + platform-arch: + description: "The target platform architecture." + required: true + runs: using: "composite" steps: @@ -42,7 +47,7 @@ runs: shell: bash - name: Install required packages for linux-x86_64 - if: matrix.platform.name == 'linux-x86_64' + if: inputs.platform-arch == 'x86_64' run: | sudo mkdir /opt/sysroot python3 webrtc-jni/src/main/cpp/dependencies/webrtc/linux/sysroot/install-sysroot.py --arch=amd64 @@ -50,7 +55,7 @@ runs: shell: bash - name: Install required packages for linux-aarch32 - if: matrix.platform.name == 'linux-aarch32' + if: inputs.platform-arch == 'aarch32' run: | sudo apt install -y gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf @@ -60,7 +65,7 @@ runs: shell: bash - name: Install required packages for linux-aarch64 - if: matrix.platform.name == 'linux-aarch64' + if: inputs.platform-arch == 'aarch64' run: | sudo apt install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu diff --git a/.github/actions/test/action.yml b/.github/actions/test/action.yml index 39b928a..39a40aa 100644 --- a/.github/actions/test/action.yml +++ b/.github/actions/test/action.yml @@ -6,13 +6,16 @@ inputs: platform-name: description: "The target platform." required: true + platform-arch: + description: "The target platform architecture." + required: true runs: using: "composite" steps: - uses: ./.github/actions/download-artifact with: - name: webrtc-java-jni-${{ inputs.platform-name }} + name: webrtc-java-jni-${{ inputs.platform-name }}-${{ inputs.platform-arch }} path: artifacts - name: Test diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4a52b05..db21e91 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,23 +21,26 @@ jobs: fail-fast: false matrix: platform: - - name: windows-x86_64 + - name: windows + arch: x86_64 runs-on: windows-2022 - - name: windows-aarch64 + - name: windows + arch: aarch64 runs-on: windows-2022 runs-on: ${{ matrix.platform.runs-on }} steps: - - uses: Kas-tle/actions/checkout@main + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 name: Checkout Repository - uses: ./.github/actions/prepare-windows name: Prepare Windows - uses: ./.github/actions/setup-gradle with: - gradle-cache-read-only: "false" + gradle-cache-read-only: ${{ github.event_name == 'pull_request' }} name: Setup Gradle - uses: ./.github/actions/build with: platform-name: ${{ matrix.platform.name }} + platform-arch: ${{ matrix.platform.arch }} name: Build test-windows: @@ -47,24 +50,25 @@ jobs: fail-fast: false matrix: platform: - - name: windows-2022_windows-x86_64 - artifact-name: windows-x86_64 + - name: windows + arch: x86_64 runs-on: windows-2022 - - name: windows-2025_windows-x86_64 - artifact-name: windows-x86_64 + - name: windows + arch: x86_64 runs-on: windows-2025 - - name: windows-11-arm_windows-aarch64 - artifact-name: windows-aarch64 + - name: windows + arch: aarch64 runs-on: windows-11-arm runs-on: ${{ matrix.platform.runs-on }} steps: - - uses: Kas-tle/actions/checkout@main + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 name: Checkout Repository - uses: ./.github/actions/setup-gradle name: Setup Gradle - uses: ./.github/actions/test with: - platform-name: ${{ matrix.platform.artifact-name }} + platform-name: ${{ matrix.platform.name }} + platform-arch: ${{ matrix.platform.arch }} name: Test build-linux: @@ -73,25 +77,31 @@ jobs: fail-fast: false matrix: platform: - - name: linux-aarch32 + - name: linux + arch: aarch32 runs-on: ubuntu-22.04 - - name: linux-aarch64 + - name: linux + arch: aarch64 runs-on: ubuntu-22.04 - - name: linux-x86_64 + - name: linux + arch: x86_64 runs-on: ubuntu-22.04 runs-on: ${{ matrix.platform.runs-on }} steps: - - uses: Kas-tle/actions/checkout@main + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 name: Checkout Repository - uses: ./.github/actions/prepare-linux + with: + platform-arch: ${{ matrix.platform.arch }} name: Prepare Linux - uses: ./.github/actions/setup-gradle with: - gradle-cache-read-only: "false" + gradle-cache-read-only: ${{ github.event_name == 'pull_request' }} name: Setup Gradle - uses: ./.github/actions/build with: platform-name: ${{ matrix.platform.name }} + platform-arch: ${{ matrix.platform.arch }} name: Build test-linux: @@ -101,33 +111,33 @@ jobs: fail-fast: false matrix: platform: - - name: ubuntu-22.04-arm_linux-aarch32 - artifact-name: linux-aarch32 + - name: linux + arch: aarch32 runs-on: ubuntu-22.04-arm java-arch: armv7 - - name: ubuntu-24.04-arm_linux-aarch32 - artifact-name: linux-aarch32 + - name: linux + arch: aarch32 runs-on: ubuntu-24.04-arm java-arch: armv7 - - name: ubuntu-22.04-arm_linux-aarch64 - artifact-name: linux-aarch64 + - name: linux + arch: aarch64 runs-on: ubuntu-22.04-arm java-arch: aarch64 - - name: ubuntu-24.04-arm_linux-aarch64 - artifact-name: linux-aarch64 + - name: linux + arch: aarch64 runs-on: ubuntu-24.04-arm java-arch: aarch64 - - name: ubuntu-22.04_linux-x86_64 - artifact-name: linux-x86_64 + - name: linux + arch: x86_64 runs-on: ubuntu-22.04 java-arch: x64 - - name: ubuntu-24.04_linux-x86_64 - artifact-name: linux-x86_64 + - name: linux + arch: x86_64 runs-on: ubuntu-24.04 java-arch: x64 runs-on: ${{ matrix.platform.runs-on }} steps: - - uses: Kas-tle/actions/checkout@main + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 name: Checkout Repository - uses: ./.github/actions/setup-gradle with: @@ -135,7 +145,8 @@ jobs: name: Setup Gradle - uses: ./.github/actions/test with: - platform-name: ${{ matrix.platform.artifact-name }} + platform-name: ${{ matrix.platform.name }} + platform-arch: ${{ matrix.platform.arch }} name: Test build-macos: @@ -144,23 +155,26 @@ jobs: fail-fast: false matrix: platform: - - name: macos-x86_64 + - name: macos + arch: x86_64 runs-on: macos-14 - - name: macos-aarch64 + - name: macos + arch: aarch64 runs-on: macos-14 runs-on: ${{ matrix.platform.runs-on }} steps: - - uses: Kas-tle/actions/checkout@main + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 name: Checkout Repository - uses: ./.github/actions/prepare-macos name: Prepare macOS - uses: ./.github/actions/setup-gradle with: - gradle-cache-read-only: "false" + gradle-cache-read-only: ${{ github.event_name == 'pull_request' }} name: Setup Gradle - uses: ./.github/actions/build with: platform-name: ${{ matrix.platform.name }} + platform-arch: ${{ matrix.platform.arch }} name: Build test-macos: @@ -170,27 +184,28 @@ jobs: fail-fast: false matrix: platform: - - name: macos-15-intel_macos-x86_64 - artifact-name: macos-x86_64 + - name: macos + arch: x86_64 runs-on: macos-15-intel - - name: macos-14_macos-aarch64 - artifact-name: macos-aarch64 + - name: macos + arch: aarch64 runs-on: macos-14 - - name: macos-15_macos-aarch64 - artifact-name: macos-aarch64 + - name: macos + arch: aarch64 runs-on: macos-15 - - name: macos-26_macos-aarch64 - artifact-name: macos-aarch64 + - name: macos + arch: aarch64 runs-on: macos-26 runs-on: ${{ matrix.platform.runs-on }} steps: - - uses: Kas-tle/actions/checkout@main + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 name: Checkout Repository - uses: ./.github/actions/setup-gradle name: Setup Gradle - uses: ./.github/actions/test with: - platform-name: ${{ matrix.platform.artifact-name }} + platform-name: ${{ matrix.platform.name }} + platform-arch: ${{ matrix.platform.arch }} name: Test detect-release: @@ -205,7 +220,7 @@ jobs: unreleased: ${{ steps.version.outputs.unreleased }} version: ${{ steps.version.outputs.version }} steps: - - uses: Kas-tle/actions/checkout@main + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 with: fetch-depth: "0" name: Checkout Repository @@ -227,7 +242,7 @@ jobs: outputs: release_id: ${{ steps.release.outputs.releaseID }} steps: - - uses: Kas-tle/actions/checkout@main + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 name: Checkout Repository - uses: ./.github/actions/setup-gradle name: Setup Gradle diff --git a/webrtc-jni/build.gradle.kts b/webrtc-jni/build.gradle.kts index d1d64be..81f20f5 100644 --- a/webrtc-jni/build.gradle.kts +++ b/webrtc-jni/build.gradle.kts @@ -37,18 +37,7 @@ if (targetPlatform == null) { targetPlatform = "$osFamily-$osArch" } -val toolchainFile = file("src/main/cpp/toolchain").resolve( - when { - targetPlatform == "linux-x86_64" -> "x86_64-linux-clang.cmake" - targetPlatform == "linux-aarch64" -> "aarch64-linux-clang.cmake" - targetPlatform == "linux-aarch32" -> "aarch32-linux-clang.cmake" - targetPlatform == "windows-x86_64" -> "x86_64-windows-clang.cmake" - targetPlatform == "windows-aarch64" -> "aarch64-windows-clang.cmake" - targetPlatform == "macos-x86_64" -> "x86_64-macos-cross.cmake" - targetPlatform == "macos-aarch64" -> "aarch64-macos-clang.cmake" - else -> "unknown-toolchain.cmake" - } -) +val toolchainFile = file("src/main/cpp/toolchain").resolve("$targetPlatform.cmake") val cmakeBuildDir = layout.buildDirectory.dir("cmake/$targetPlatform") diff --git a/webrtc-jni/src/main/cpp/toolchain/aarch32-linux-clang.cmake b/webrtc-jni/src/main/cpp/toolchain/linux-aarch32.cmake similarity index 100% rename from webrtc-jni/src/main/cpp/toolchain/aarch32-linux-clang.cmake rename to webrtc-jni/src/main/cpp/toolchain/linux-aarch32.cmake diff --git a/webrtc-jni/src/main/cpp/toolchain/aarch64-linux-clang.cmake b/webrtc-jni/src/main/cpp/toolchain/linux-aarch64.cmake similarity index 100% rename from webrtc-jni/src/main/cpp/toolchain/aarch64-linux-clang.cmake rename to webrtc-jni/src/main/cpp/toolchain/linux-aarch64.cmake diff --git a/webrtc-jni/src/main/cpp/toolchain/x86_64-linux-clang.cmake b/webrtc-jni/src/main/cpp/toolchain/linux-x86_64.cmake similarity index 100% rename from webrtc-jni/src/main/cpp/toolchain/x86_64-linux-clang.cmake rename to webrtc-jni/src/main/cpp/toolchain/linux-x86_64.cmake diff --git a/webrtc-jni/src/main/cpp/toolchain/aarch64-macos-clang.cmake b/webrtc-jni/src/main/cpp/toolchain/macos-aarch64.cmake similarity index 100% rename from webrtc-jni/src/main/cpp/toolchain/aarch64-macos-clang.cmake rename to webrtc-jni/src/main/cpp/toolchain/macos-aarch64.cmake diff --git a/webrtc-jni/src/main/cpp/toolchain/x86_64-macos-cross.cmake b/webrtc-jni/src/main/cpp/toolchain/macos-x86_64.cmake similarity index 100% rename from webrtc-jni/src/main/cpp/toolchain/x86_64-macos-cross.cmake rename to webrtc-jni/src/main/cpp/toolchain/macos-x86_64.cmake diff --git a/webrtc-jni/src/main/cpp/toolchain/aarch64-windows-clang.cmake b/webrtc-jni/src/main/cpp/toolchain/windows-aarch64.cmake similarity index 100% rename from webrtc-jni/src/main/cpp/toolchain/aarch64-windows-clang.cmake rename to webrtc-jni/src/main/cpp/toolchain/windows-aarch64.cmake diff --git a/webrtc-jni/src/main/cpp/toolchain/x86_64-windows-clang.cmake b/webrtc-jni/src/main/cpp/toolchain/windows-x86_64.cmake similarity index 100% rename from webrtc-jni/src/main/cpp/toolchain/x86_64-windows-clang.cmake rename to webrtc-jni/src/main/cpp/toolchain/windows-x86_64.cmake diff --git a/webrtc/build.gradle.kts b/webrtc/build.gradle.kts index 9fcdbaf..09c226e 100644 --- a/webrtc/build.gradle.kts +++ b/webrtc/build.gradle.kts @@ -103,7 +103,7 @@ publishing { // These jars are downloaded by the GitHub Actions "Publish" job into a folder val nativeStagingdir = file(rootProject.projectDir.resolve("native-staging")) if (nativeStagingdir.exists()) { - logger.lifecycle("Attaching native jars from: ${nativeStagingdir.absolutePath}") + logger.lifecycle("Maven publication will include native jars from: ${nativeStagingdir.absolutePath}") // list files in dir and subdirs val nativeFiles: Sequence = nativeStagingdir.walkTopDown() @@ -116,7 +116,7 @@ publishing { .replace("webrtc-java-${version}-", "") .replace(".jar", "") classifier = classifierStr - logger.lifecycle("Attached native jar: ${jarFile.name} with classifier: ${classifierStr}") + logger.lifecycle("Attached native jar to maven publication: ${jarFile.name} with classifier: ${classifierStr}") } } }