From f1b8ff05a2343089d40ddaadcbcf6c49e4f7a215 Mon Sep 17 00:00:00 2001 From: davidliu Date: Thu, 28 Mar 2024 23:11:34 +0900 Subject: [PATCH 001/144] android, ios: remove track from remoteTracks in onRemoveTrack (#6) --- .../main/java/com/oney/WebRTCModule/PeerConnectionObserver.java | 2 ++ ios/RCTWebRTC/WebRTCModule+RTCPeerConnection.m | 2 ++ 2 files changed, 4 insertions(+) diff --git a/android/src/main/java/com/oney/WebRTCModule/PeerConnectionObserver.java b/android/src/main/java/com/oney/WebRTCModule/PeerConnectionObserver.java index 1b759f69c..03ae9b0e1 100644 --- a/android/src/main/java/com/oney/WebRTCModule/PeerConnectionObserver.java +++ b/android/src/main/java/com/oney/WebRTCModule/PeerConnectionObserver.java @@ -591,6 +591,8 @@ public void onRemoveTrack(RtpReceiver receiver) { params.putInt("pcId", this.id); params.putString("receiverId", receiver.id()); + remoteTracks.remove(receiver.id()); + webRTCModule.sendEvent("peerConnectionOnRemoveTrack", params); }); }; diff --git a/ios/RCTWebRTC/WebRTCModule+RTCPeerConnection.m b/ios/RCTWebRTC/WebRTCModule+RTCPeerConnection.m index fb9beeb1f..5d968d83b 100644 --- a/ios/RCTWebRTC/WebRTCModule+RTCPeerConnection.m +++ b/ios/RCTWebRTC/WebRTCModule+RTCPeerConnection.m @@ -922,6 +922,8 @@ - (void)peerConnection:(RTC_OBJC_TYPE(RTCPeerConnection) *)peerConnection params[@"pcId"] = peerConnection.reactTag; params[@"receiverId"] = rtpReceiver.receiverId; + [peerConnection.remoteTracks removeObjectForKey:rtpReceiver.receiverId]; + [self sendEventWithName:kEventPeerConnectionOnRemoveTrack body:params]; }); } From fed67a4e6ed8eb726eb27443fb4b8a6d7e518692 Mon Sep 17 00:00:00 2001 From: davidliu Date: Thu, 23 Nov 2023 17:17:28 +0900 Subject: [PATCH 002/144] android, ios: update webrtc to m114 --- android/build.gradle | 2 +- livekit-react-native-webrtc.podspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 43d32e29d..39fa040df 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -31,5 +31,5 @@ android { dependencies { implementation 'com.facebook.react:react-native:+' implementation 'com.github.jiangdongguo.AndroidUSBCamera:libausbc:3.3.3' - api 'io.github.webrtc-sdk:android:104.5112.10' + api 'io.github.webrtc-sdk:android:114.5735.05' } diff --git a/livekit-react-native-webrtc.podspec b/livekit-react-native-webrtc.podspec index 3efc8ec49..b0b36d30e 100644 --- a/livekit-react-native-webrtc.podspec +++ b/livekit-react-native-webrtc.podspec @@ -19,5 +19,5 @@ Pod::Spec.new do |s| s.libraries = 'c', 'sqlite3', 'stdc++' s.framework = 'AudioToolbox','AVFoundation', 'CoreAudio', 'CoreGraphics', 'CoreVideo', 'GLKit', 'VideoToolbox' s.dependency 'React-Core' - s.dependency 'WebRTC-SDK', '=104.5112.17' + s.dependency 'WebRTC-SDK', '=114.5735.08' end From 8718032ca3f19e899a1fb843645526a0a2f51002 Mon Sep 17 00:00:00 2001 From: davidliu Date: Mon, 8 Apr 2024 20:02:59 +0900 Subject: [PATCH 003/144] release 114.1.0-beta.0 --- README.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 01a56d35a..79b854099 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ Software encode/decode factories have been enabled by default. ## WebRTC Revision -* Currently used revision: [M118](https://github.com/jitsi/webrtc/tree/M118) +* Currently used revision: [M114](https://github.com/webrtc-sdk/webrtc/tree/m114_release) * Supported architectures * Android: armeabi-v7a, arm64-v8a, x86, x86_64 * iOS: arm64, x86_64 diff --git a/package-lock.json b/package-lock.json index 2cb5aa43a..7e4885136 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@livekit/react-native-webrtc", - "version": "104.0.0", + "version": "114.1.0-beta.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@livekit/react-native-webrtc", - "version": "104.0.0", + "version": "114.1.0-beta.0", "license": "MIT", "dependencies": { "base64-js": "1.5.1", diff --git a/package.json b/package.json index e9b8e1dda..1195bc3ec 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@livekit/react-native-webrtc", - "version": "104.0.0", + "version": "114.1.0-beta.0", "repository": { "type": "git", "url": "git+https://github.com/livekit/react-native-webrtc.git" From 2652c6b3edb282777405bed92c17a7c5be7e51e6 Mon Sep 17 00:00:00 2001 From: davidliu Date: Mon, 8 Apr 2024 21:04:27 +0900 Subject: [PATCH 004/144] release 114.1.0 updated upstream react-native-webrtc to 118.0.4 f1b8ff0 android, ios: remove track from remoteTracks in onRemoveTrack (#6) ( davidliu 2024-03-28 23:11:34 +0900) --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7e4885136..2759a0742 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@livekit/react-native-webrtc", - "version": "114.1.0-beta.0", + "version": "114.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@livekit/react-native-webrtc", - "version": "114.1.0-beta.0", + "version": "114.1.0", "license": "MIT", "dependencies": { "base64-js": "1.5.1", diff --git a/package.json b/package.json index 1195bc3ec..899cfaec6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@livekit/react-native-webrtc", - "version": "114.1.0-beta.0", + "version": "114.1.0", "repository": { "type": "git", "url": "git+https://github.com/livekit/react-native-webrtc.git" From 3de7f5bd0301c934677bbfd048ef58c15e1b8baa Mon Sep 17 00:00:00 2001 From: davidliu Date: Tue, 9 Apr 2024 00:13:27 +0900 Subject: [PATCH 005/144] release 114.1.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1a03f67 android: drop UVC camera support ( Saúl Ibarra Corretgé 2024-04-04 17:11:34 +0200) --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2759a0742..337051b34 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@livekit/react-native-webrtc", - "version": "114.1.0", + "version": "114.1.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@livekit/react-native-webrtc", - "version": "114.1.0", + "version": "114.1.1", "license": "MIT", "dependencies": { "base64-js": "1.5.1", diff --git a/package.json b/package.json index 899cfaec6..9a615c14c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@livekit/react-native-webrtc", - "version": "114.1.0", + "version": "114.1.1", "repository": { "type": "git", "url": "git+https://github.com/livekit/react-native-webrtc.git" From f1bc9ffe73075f46c523fe91ac7b04fda44dbb1f Mon Sep 17 00:00:00 2001 From: davidliu Date: Tue, 9 Apr 2024 12:01:07 +0900 Subject: [PATCH 006/144] Update AndroidInstallation.md --- Documentation/AndroidInstallation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/AndroidInstallation.md b/Documentation/AndroidInstallation.md index da50cccba..3181e2bc0 100644 --- a/Documentation/AndroidInstallation.md +++ b/Documentation/AndroidInstallation.md @@ -34,7 +34,7 @@ If you plan to also support Bluetooth devices then also add the following. ### Screen-sharing -Starting with version 118.0.2 a foreground service is included in this library in order to make +Starting with version 114.1.0 a foreground service is included in this library in order to make screen-sharing possible under Android 14 rules. If you want to enable it, first declare the following permissions: From 157729cc45527443762faf27986dd0bf9b154e5e Mon Sep 17 00:00:00 2001 From: davidliu Date: Fri, 3 May 2024 17:45:56 +0900 Subject: [PATCH 007/144] ios: update webrtc to 114.5735.10 (#7) * ios: update webrtc to 114.5735.10 * make podspec fuzzy --- livekit-react-native-webrtc.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/livekit-react-native-webrtc.podspec b/livekit-react-native-webrtc.podspec index b0b36d30e..aec23ac35 100644 --- a/livekit-react-native-webrtc.podspec +++ b/livekit-react-native-webrtc.podspec @@ -19,5 +19,5 @@ Pod::Spec.new do |s| s.libraries = 'c', 'sqlite3', 'stdc++' s.framework = 'AudioToolbox','AVFoundation', 'CoreAudio', 'CoreGraphics', 'CoreVideo', 'GLKit', 'VideoToolbox' s.dependency 'React-Core' - s.dependency 'WebRTC-SDK', '=114.5735.08' + s.dependency 'WebRTC-SDK', '~>114.5735.10' end From 5abdfbeab73db1ac521d85c7c90ab72605164ad6 Mon Sep 17 00:00:00 2001 From: davidliu Date: Fri, 3 May 2024 17:46:40 +0900 Subject: [PATCH 008/144] release 114.1.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 157729c ios: update webrtc to 114.5735.10 (#7) ( davidliu 2024-05-03 17:45:56 +0900) 495658d ci: fix build (#1562) ( davidliu 2024-05-03 17:18:31 +0900) 822cac7 release 118.0.7 ( Saúl Ibarra Corretgé 2024-04-18 13:32:21 +0200) 882f8b1 release 118.0.6 ( Saúl Ibarra Corretgé 2024-04-11 23:03:33 +0200) 8dfc9c3 Revert "android, ios: remove track when removed from peerconnection (#1525)" (#1550) ( Johnathon Weaver 2024-04-17 14:38:36 +0800) c0c446a ios: fix not being able to deactivate encodings ( Saúl Ibarra Corretgé 2024-04-11 22:31:38 +0200) 5d85486 android,ios: don't reject promise for getStats (#1541) ( davidliu 2024-04-11 00:58:52 +0900) f1bc9ff Update AndroidInstallation.md ( davidliu 2024-04-09 12:01:07 +0900) --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 337051b34..59013f99e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@livekit/react-native-webrtc", - "version": "114.1.1", + "version": "114.1.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@livekit/react-native-webrtc", - "version": "114.1.1", + "version": "114.1.2", "license": "MIT", "dependencies": { "base64-js": "1.5.1", diff --git a/package.json b/package.json index 9a615c14c..592a6c6f8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@livekit/react-native-webrtc", - "version": "114.1.1", + "version": "114.1.2", "repository": { "type": "git", "url": "git+https://github.com/livekit/react-native-webrtc.git" From 4e442f1f34299f84001bd3e202a11260c2914416 Mon Sep 17 00:00:00 2001 From: davidliu Date: Wed, 22 May 2024 15:47:12 +0900 Subject: [PATCH 009/144] Update android webrtc to 114.5735.11 --- android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/build.gradle b/android/build.gradle index 6064f3f6d..e2dd50a39 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -30,5 +30,5 @@ android { dependencies { implementation 'com.facebook.react:react-native:+' - api 'io.github.webrtc-sdk:android:114.5735.05' + api 'io.github.webrtc-sdk:android:114.5735.11' } From 03ab65b8475522990fd5eb2f8ef02bb99f42218d Mon Sep 17 00:00:00 2001 From: davidliu Date: Wed, 22 May 2024 16:01:48 +0900 Subject: [PATCH 010/144] release 114.1.3 4e442f1 Update android webrtc to 114.5735.11 ( davidliu 2024-05-22 15:47:12 +0900) --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 59013f99e..3f11a6457 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@livekit/react-native-webrtc", - "version": "114.1.2", + "version": "114.1.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@livekit/react-native-webrtc", - "version": "114.1.2", + "version": "114.1.3", "license": "MIT", "dependencies": { "base64-js": "1.5.1", diff --git a/package.json b/package.json index 592a6c6f8..67d85e602 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@livekit/react-native-webrtc", - "version": "114.1.2", + "version": "114.1.3", "repository": { "type": "git", "url": "git+https://github.com/livekit/react-native-webrtc.git" From 651373e05b35cb337785a109a85629d629e057db Mon Sep 17 00:00:00 2001 From: davidliu Date: Sat, 25 May 2024 20:57:36 +0900 Subject: [PATCH 011/144] android: only change capture format for screen if dimen actually changed (#8) --- .../AbstractVideoCaptureController.java | 4 +-- .../WebRTCModule/ScreenCaptureController.java | 26 +++++++++++-------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/android/src/main/java/com/oney/WebRTCModule/AbstractVideoCaptureController.java b/android/src/main/java/com/oney/WebRTCModule/AbstractVideoCaptureController.java index d21aab531..393f73c51 100644 --- a/android/src/main/java/com/oney/WebRTCModule/AbstractVideoCaptureController.java +++ b/android/src/main/java/com/oney/WebRTCModule/AbstractVideoCaptureController.java @@ -3,8 +3,8 @@ import org.webrtc.VideoCapturer; public abstract class AbstractVideoCaptureController { - private final int width; - private final int height; + protected int width; + protected int height; private final int fps; /** diff --git a/android/src/main/java/com/oney/WebRTCModule/ScreenCaptureController.java b/android/src/main/java/com/oney/WebRTCModule/ScreenCaptureController.java index 39964eea2..9d50263cb 100644 --- a/android/src/main/java/com/oney/WebRTCModule/ScreenCaptureController.java +++ b/android/src/main/java/com/oney/WebRTCModule/ScreenCaptureController.java @@ -41,17 +41,21 @@ public void onOrientationChanged(int orientation) { DisplayMetrics displayMetrics = DisplayUtils.getDisplayMetrics((Activity) context); final int width = displayMetrics.widthPixels; final int height = displayMetrics.heightPixels; - - // Pivot to the executor thread because videoCapturer.changeCaptureFormat runs in the main - // thread and may deadlock. - ThreadUtils.runOnExecutor(() -> { - try { - videoCapturer.changeCaptureFormat(width, height, DEFAULT_FPS); - } catch (Exception ex) { - // We ignore exceptions here. The video capturer runs on its own - // thread and we cannot synchronize with it. - } - }); + if (width != ScreenCaptureController.this.width || height != ScreenCaptureController.this.height) { + ScreenCaptureController.this.width = width; + ScreenCaptureController.this.height = height; + + // Pivot to the executor thread because videoCapturer.changeCaptureFormat runs in the main + // thread and may deadlock. + ThreadUtils.runOnExecutor(() -> { + try { + videoCapturer.changeCaptureFormat(width, height, DEFAULT_FPS); + } catch (Exception ex) { + // We ignore exceptions here. The video capturer runs on its own + // thread and we cannot synchronize with it. + } + }); + } } }; From c8829cb8bb044ba37708e56353a7d135f493e4b7 Mon Sep 17 00:00:00 2001 From: davidliu Date: Sun, 26 May 2024 21:19:48 +0900 Subject: [PATCH 012/144] release 114.1.4 651373e android: only change capture format for screen if dimen actually changed (#8) ( davidliu 2024-05-25 20:57:36 +0900) --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3f11a6457..573596e7b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@livekit/react-native-webrtc", - "version": "114.1.3", + "version": "114.1.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@livekit/react-native-webrtc", - "version": "114.1.3", + "version": "114.1.4", "license": "MIT", "dependencies": { "base64-js": "1.5.1", diff --git a/package.json b/package.json index 67d85e602..0a95ce63e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@livekit/react-native-webrtc", - "version": "114.1.3", + "version": "114.1.4", "repository": { "type": "git", "url": "git+https://github.com/livekit/react-native-webrtc.git" From 29210ac2bec8201ff452a8287411926f1397fa66 Mon Sep 17 00:00:00 2001 From: davidliu Date: Fri, 21 Jun 2024 22:05:29 +0900 Subject: [PATCH 013/144] android: release audio device module after creating factory --- .../main/java/com/oney/WebRTCModule/WebRTCModule.java | 11 +++-------- examples/GumTestApp/package.json | 2 +- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/android/src/main/java/com/oney/WebRTCModule/WebRTCModule.java b/android/src/main/java/com/oney/WebRTCModule/WebRTCModule.java index f32bac9c9..6c6ed9d38 100644 --- a/android/src/main/java/com/oney/WebRTCModule/WebRTCModule.java +++ b/android/src/main/java/com/oney/WebRTCModule/WebRTCModule.java @@ -102,6 +102,9 @@ public WebRTCModule(ReactApplicationContext reactContext) { .setVideoDecoderFactory(decoderFactory) .createPeerConnectionFactory(); + // PeerConnectionFactory now owns the adm native pointer, and we don't need it anymore. + adm.release(); + // Saving the encoder and decoder factories to get codec info later when needed. mVideoEncoderFactory = encoderFactory; mVideoDecoderFactory = decoderFactory; @@ -116,14 +119,6 @@ public String getName() { return "WebRTCModule"; } - @Override - public void onCatalystInstanceDestroy() { - if (mAudioDeviceModule != null) { - mAudioDeviceModule.release(); - } - super.onCatalystInstanceDestroy(); - } - private PeerConnection getPeerConnection(int id) { PeerConnectionObserver pco = mPeerConnectionObservers.get(id); return (pco == null) ? null : pco.getPeerConnection(); diff --git a/examples/GumTestApp/package.json b/examples/GumTestApp/package.json index 7bd8507e5..9dbcaade0 100644 --- a/examples/GumTestApp/package.json +++ b/examples/GumTestApp/package.json @@ -13,7 +13,7 @@ "dependencies": { "react": "18.2.0", "react-native": "0.71.4", - "react-native-webrtc": "*" + "@livekit/react-native-webrtc": "*" }, "devDependencies": { "@babel/core": "^7.20.0", From cde6b51781fa151598582bb14e6624139daacc33 Mon Sep 17 00:00:00 2001 From: davidliu Date: Fri, 21 Jun 2024 22:06:45 +0900 Subject: [PATCH 014/144] release 114.1.5 29210ac android: release audio device module after creating factory ( davidliu 2024-06-21 22:05:29 +0900) --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 573596e7b..6b6614b47 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@livekit/react-native-webrtc", - "version": "114.1.4", + "version": "114.1.5", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@livekit/react-native-webrtc", - "version": "114.1.4", + "version": "114.1.5", "license": "MIT", "dependencies": { "base64-js": "1.5.1", diff --git a/package.json b/package.json index 0a95ce63e..33b27846b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@livekit/react-native-webrtc", - "version": "114.1.4", + "version": "114.1.5", "repository": { "type": "git", "url": "git+https://github.com/livekit/react-native-webrtc.git" From 2d153e152c0134337ace59f78ba6b9e204d6601a Mon Sep 17 00:00:00 2001 From: davidliu Date: Mon, 24 Jun 2024 11:20:10 +0900 Subject: [PATCH 015/144] Merge upstream and update webrtc to M125 (#9) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * webrtc: update WebRTC to M124 * api: allow sdpMid / sdpLineIndex to be null in RTCIceCandidate Having both as null is still an error. Fixes: #1518 * ios: refactor rendering in RTCVideoView The way the renderer is implemented is as follows: there is a UIView which holds on to a RTCMTLVideoView, which does the actual rendering in metal. Rather than using our own home-grown mechanism to layout the views, just make sure the Metal view takes 100% of the space of our view, and then use the `videoContentMode` property to set it to cover or contain, matching the way a browser would do it. This greatly simplifies the code because we lonnger care about the video size, the Metal renderer makes the adjustments autmagically. In addition, the mirror and object-fit properties are only applied once, when they change, not on every layout change, which is unnecessary. * ios: add all available camera device types * preserve order * release 124.0.1 20cf1d5 preserve order ( Burak KIYAK 2024-05-03 13:41:59 +0200) 64e8298 ios: add all available camera device types ( Burak KIYAK 2024-04-30 12:30:38 +0200) f36b6b8 ios: refactor rendering in RTCVideoView ( Saúl Ibarra Corretgé 2024-06-11 09:35:36 +0200) * build(deps-dev): bump braces from 3.0.2 to 3.0.3 (#1578) Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3. - [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md) - [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3) --- updated-dependencies: - dependency-name: braces dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * mark for beta release --------- Signed-off-by: dependabot[bot] Co-authored-by: Saúl Ibarra Corretgé Co-authored-by: omerts Co-authored-by: Saúl Ibarra Corretgé Co-authored-by: Burak KIYAK Co-authored-by: Burak KIYAK Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/android_ci.yml | 5 +- README.md | 4 +- android/build.gradle | 2 +- .../com/oney/WebRTCModule/WebRTCModule.java | 12 +- examples/GumTestApp/App.js | 2 +- .../ios/GumTestApp.xcodeproj/project.pbxproj | 22 +- examples/GumTestApp/ios/Podfile | 2 +- ios/RCTWebRTC/RCTConvert+WebRTC.m | 9 +- ios/RCTWebRTC/RTCVideoViewManager.m | 203 ++++-------------- ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m | 2 +- ios/RCTWebRTC/WebRTCModule+Transceivers.m | 24 +-- livekit-react-native-webrtc.podspec | 2 +- package-lock.json | 32 +-- package.json | 2 +- src/RTCIceCandidate.ts | 8 +- src/RTCPeerConnection.ts | 11 +- 16 files changed, 101 insertions(+), 241 deletions(-) diff --git a/.github/workflows/android_ci.yml b/.github/workflows/android_ci.yml index 04373cd32..5d0ca13e0 100644 --- a/.github/workflows/android_ci.yml +++ b/.github/workflows/android_ci.yml @@ -14,7 +14,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - + - uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '17' - uses: actions/setup-node@v3 with: node-version: '16.x' diff --git a/README.md b/README.md index 79b854099..abd0f0ab0 100644 --- a/README.md +++ b/README.md @@ -39,12 +39,12 @@ Software encode/decode factories have been enabled by default. ## WebRTC Revision -* Currently used revision: [M114](https://github.com/webrtc-sdk/webrtc/tree/m114_release) +* Currently used revision: [M125](https://github.com/webrtc-sdk/webrtc/tree/m125_release) * Supported architectures * Android: armeabi-v7a, arm64-v8a, x86, x86_64 * iOS: arm64, x86_64 * tvOS: arm64 - * macOS: (temporarily disabled) + * macOS: arm64, x86_64 ## Getting Started diff --git a/android/build.gradle b/android/build.gradle index e2dd50a39..eaf3d982e 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -30,5 +30,5 @@ android { dependencies { implementation 'com.facebook.react:react-native:+' - api 'io.github.webrtc-sdk:android:114.5735.11' + api 'io.github.webrtc-sdk:android:125.6422.02' } diff --git a/android/src/main/java/com/oney/WebRTCModule/WebRTCModule.java b/android/src/main/java/com/oney/WebRTCModule/WebRTCModule.java index 6c6ed9d38..c508b7c51 100644 --- a/android/src/main/java/com/oney/WebRTCModule/WebRTCModule.java +++ b/android/src/main/java/com/oney/WebRTCModule/WebRTCModule.java @@ -1270,16 +1270,16 @@ public void peerConnectionAddICECandidate(int pcId, ReadableMap candidateMap, Pr return; } - if (!(candidateMap.hasKey("sdpMid") && candidateMap.hasKey("sdpMLineIndex") - && candidateMap.hasKey("sdpMid"))) { + if (!candidateMap.hasKey("sdpMid") && !candidateMap.hasKey("sdpMLineIndex")) { promise.reject("E_TYPE_ERROR", "Invalid argument"); return; } - IceCandidate candidate = new IceCandidate(candidateMap.getString("sdpMid"), - candidateMap.getInt("sdpMLineIndex"), - candidateMap.getString("candidate")); - + IceCandidate candidate = new IceCandidate( + candidateMap.hasKey("sdpMid") && !candidateMap.isNull("sdpMid") ? candidateMap.getString("sdpMid") : "", + candidateMap.hasKey("sdpMLineIndex") && !candidateMap.isNull("sdpMLineIndex") ? candidateMap.getInt("sdpMLineIndex") : 0, + candidateMap.getString("candidate")); + peerConnection.addIceCandidate(candidate, new AddIceObserver() { @Override public void onAddSuccess() { diff --git a/examples/GumTestApp/App.js b/examples/GumTestApp/App.js index e9e9fe6c3..427f2592c 100644 --- a/examples/GumTestApp/App.js +++ b/examples/GumTestApp/App.js @@ -15,7 +15,7 @@ import { StatusBar, } from 'react-native'; import { Colors } from 'react-native/Libraries/NewAppScreen'; -import { mediaDevices, RTCView } from 'react-native-webrtc'; +import { mediaDevices, RTCView } from '@livekit/react-native-webrtc'; const App = () => { diff --git a/examples/GumTestApp/ios/GumTestApp.xcodeproj/project.pbxproj b/examples/GumTestApp/ios/GumTestApp.xcodeproj/project.pbxproj index 26e5d225f..6d072ddce 100644 --- a/examples/GumTestApp/ios/GumTestApp.xcodeproj/project.pbxproj +++ b/examples/GumTestApp/ios/GumTestApp.xcodeproj/project.pbxproj @@ -359,7 +359,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh"; + shellScript = "# Fix for machines using nvm\nif [[ -s \"$HOME/.nvm/nvm.sh\" ]]; then\n. \"$HOME/.nvm/nvm.sh\"\nelif [[ -x \"$(command -v brew)\" && -s \"$(brew --prefix nvm)/nvm.sh\" ]]; then\n. \"$(brew --prefix nvm)/nvm.sh\"\nfi\n\nexport NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh\n"; }; 2D02E4CB1E0B4B27006451C7 /* Bundle React Native Code And Images */ = { isa = PBXShellScriptBuildPhase; @@ -400,18 +400,12 @@ ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-GumTestApp/Pods-GumTestApp-frameworks.sh", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/Flipper-DoubleConversion/double-conversion.framework/double-conversion", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/Flipper-Glog/glog.framework/glog", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/JitsiWebRTC/WebRTC.framework/WebRTC", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenSSL-Universal/OpenSSL.framework/OpenSSL", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/WebRTC-SDK/WebRTC.framework/WebRTC", "${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/double-conversion.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/glog.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WebRTC.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OpenSSL.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework", ); runOnlyForDeploymentPostprocessing = 0; @@ -466,18 +460,12 @@ ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-GumTestApp-GumTestAppTests/Pods-GumTestApp-GumTestAppTests-frameworks.sh", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/Flipper-DoubleConversion/double-conversion.framework/double-conversion", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/Flipper-Glog/glog.framework/glog", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/JitsiWebRTC/WebRTC.framework/WebRTC", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenSSL-Universal/OpenSSL.framework/OpenSSL", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/WebRTC-SDK/WebRTC.framework/WebRTC", "${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/double-conversion.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/glog.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WebRTC.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OpenSSL.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework", ); runOnlyForDeploymentPostprocessing = 0; @@ -657,7 +645,7 @@ "-ObjC", "-lc++", ); - PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.lk.--PRODUCT-NAME-rfc1034identifier-"; PRODUCT_NAME = GumTestApp; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -680,7 +668,7 @@ "-ObjC", "-lc++", ); - PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.lk.--PRODUCT-NAME-rfc1034identifier-"; PRODUCT_NAME = GumTestApp; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; diff --git a/examples/GumTestApp/ios/Podfile b/examples/GumTestApp/ios/Podfile index 8be5f3b28..d52ad8f37 100644 --- a/examples/GumTestApp/ios/Podfile +++ b/examples/GumTestApp/ios/Podfile @@ -1,7 +1,7 @@ require_relative '../node_modules/react-native/scripts/react_native_pods' require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' -platform :ios, min_ios_version_supported +platform :ios, 13.0 prepare_react_native_project! # If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set. diff --git a/ios/RCTWebRTC/RCTConvert+WebRTC.m b/ios/RCTWebRTC/RCTConvert+WebRTC.m index 78db606aa..363fe4add 100644 --- a/ios/RCTWebRTC/RCTConvert+WebRTC.m +++ b/ios/RCTWebRTC/RCTConvert+WebRTC.m @@ -43,13 +43,8 @@ + (RTCIceCandidate *)RTCIceCandidate:(id)json { return nil; } - if (json[@"sdpMid"] == nil) { - RCTLogConvertError(json, @".sdpMid must not be null"); - return nil; - } - - if (json[@"sdpMLineIndex"] == nil) { - RCTLogConvertError(json, @".sdpMLineIndex must not be null"); + if (json[@"sdpMid"] == nil && json[@"sdpMLineIndex"] == nil) { + RCTLogConvertError(json, @".sdpMid and .sdpMLineIndex must not be both null"); return nil; } diff --git a/ios/RCTWebRTC/RTCVideoViewManager.m b/ios/RCTWebRTC/RTCVideoViewManager.m index c0c0f51d7..92c19cb17 100644 --- a/ios/RCTWebRTC/RTCVideoViewManager.m +++ b/ios/RCTWebRTC/RTCVideoViewManager.m @@ -3,10 +3,10 @@ #import #import -#if !TARGET_OS_OSX -#import -#else +#if TARGET_OS_OSX #import +#else +#import #endif #import #import @@ -28,7 +28,7 @@ typedef NS_ENUM(NSInteger, RTCVideoViewObjectFit) { * The replaced content is sized to maintain its aspect ratio while fitting * within the element's content box. */ - RTCVideoViewObjectFitContain, + RTCVideoViewObjectFitContain = 1, /** * The cover value defined by https://www.w3.org/TR/css3-images/#object-fit: * @@ -43,10 +43,10 @@ typedef NS_ENUM(NSInteger, RTCVideoViewObjectFit) { * element. */ -#if !TARGET_OS_OSX -@interface RTCVideoView : UIView +#if TARGET_OS_OSX +@interface RTCVideoView : NSView #else -@interface RTCVideoView : NSView +@interface RTCVideoView : UIView #endif /** @@ -65,14 +65,12 @@ @interface RTCVideoView : NSView @property(nonatomic) RTCVideoViewObjectFit objectFit; /** - * The {@link RRTCVideoRenderer} which implements the actual rendering and which - * fits within this view so that the rendered video preserves the aspect ratio of - * {@link #_videoSize}. + * The {@link RRTCVideoRenderer} which implements the actual rendering. */ -#if !TARGET_OS_OSX -@property(nonatomic, readonly) __kindof UIView *videoView; +#if TARGET_OS_OSX +@property(nonatomic, readonly) RTCMTLNSVideoView *videoView; #else -@property(nonatomic, readonly) __kindof NSView *videoView; +@property(nonatomic, readonly) RTCMTLVideoView *videoView; #endif /** @@ -87,12 +85,7 @@ @interface RTCVideoView : NSView @end -@implementation RTCVideoView { - /** - * The width and height of the video (frames) rendered by {@link #subview}. - */ - CGSize _videoSize; -} +@implementation RTCVideoView @synthesize videoView = _videoView; @@ -100,11 +93,11 @@ @implementation RTCVideoView { * Tells this view that its window object changed. */ - (void)didMoveToWindow { - // XXX This RTCVideoView strongly retains its videoTrack. The latter strongly + // This RTCVideoView strongly retains its videoTrack. The latter strongly // retains the former as well though because RTCVideoTrack strongly retains // the RTCVideoRenderers added to it. In other words, there is a cycle of - // strong retainments and, consequently, there is a memory leak. In order to - // break the cycle, have this RTCVideoView as the RTCVideoRenderer of its + // strong retainments. In order to break the cycle, and avoid a leak, + // have this RTCVideoView as the RTCVideoRenderer of its // videoTrack only while this view resides in a window. RTCVideoTrack *videoTrack = self.videoTrack; @@ -117,13 +110,6 @@ - (void)didMoveToWindow { dispatch_async(_module.workerQueue, ^{ [videoTrack removeRenderer:self.videoView]; }); - _videoSize.height = 0; - _videoSize.width = 0; -#if !TARGET_OS_OSX - [self setNeedsLayout]; -#else - self.needsLayout = YES; -#endif } } } @@ -136,88 +122,30 @@ - (void)didMoveToWindow { */ - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { -#if !TARGET_OS_OSX - RTCMTLVideoView *subview = [[RTCMTLVideoView alloc] initWithFrame:CGRectZero]; - subview.delegate = self; - _videoView = subview; -#else +#if TARGET_OS_OSX RTCMTLNSVideoView *subview = [[RTCMTLNSVideoView alloc] initWithFrame:CGRectZero]; subview.wantsLayer = true; - subview.delegate = self; + _videoView = subview; +#else + RTCMTLVideoView *subview = [[RTCMTLVideoView alloc] initWithFrame:CGRectZero]; _videoView = subview; #endif - - _videoSize.height = 0; - _videoSize.width = 0; - -#if !TARGET_OS_OSX - self.opaque = NO; -#endif - [self addSubview:self.videoView]; } + return self; } -/** - * Lays out the subview of this instance while preserving the aspect ratio of - * the video it renders. - */ - -#if !TARGET_OS_OSX -- (void)layoutSubviews { -#else +#if TARGET_OS_OSX - (void)layout { -#endif -#if !TARGET_OS_OSX - UIView *subview = self.videoView; + [super layout]; #else - NSView *subview = self.videoView; +- (void)layoutSubviews { + [super layoutSubviews]; #endif - if (!subview) { - return; - } - CGFloat width = _videoSize.width, height = _videoSize.height; - CGRect newValue; - if (width <= 0 || height <= 0) { - newValue = self.bounds; - } else if (RTCVideoViewObjectFitCover == self.objectFit) { // cover - newValue = self.bounds; - // Is there a real need to scale subview? - if (newValue.size.width != width || newValue.size.height != height) { - CGFloat scaleFactor = MAX(newValue.size.width / width, newValue.size.height / height); - // Scale both width and height in order to make it obvious that the aspect - // ratio is preserved. - width *= scaleFactor; - height *= scaleFactor; - newValue.origin.x += (newValue.size.width - width) / 2.0; - newValue.origin.y += (newValue.size.height - height) / 2.0; - newValue.size.width = width; - newValue.size.height = height; - } - } else { // contain - // The implementation is in accord with - // https://www.w3.org/TR/html5/embedded-content-0.html#the-video-element: - // - // In the absence of style rules to the contrary, video content should be - // rendered inside the element's playback area such that the video content - // is shown centered in the playback area at the largest possible size that - // fits completely within it, with the video content's aspect ratio being - // preserved. Thus, if the aspect ratio of the playback area does not match - // the aspect ratio of the video, the video will be shown letterboxed or - // pillarboxed. Areas of the element's playback area that do not contain the - // video represent nothing. - newValue = AVMakeRectWithAspectRatioInsideRect(CGSizeMake(width, height), self.bounds); - } - - CGRect oldValue = subview.frame; - if (newValue.origin.x != oldValue.origin.x || newValue.origin.y != oldValue.origin.y || - newValue.size.width != oldValue.size.width || newValue.size.height != oldValue.size.height) { - subview.frame = newValue; - } - - [subview.layer setAffineTransform:self.mirror ? CGAffineTransformMakeScale(-1.0, 1.0) : CGAffineTransformIdentity]; + CGRect bounds = self.bounds; + self.videoView.frame = bounds; } /** @@ -231,11 +159,7 @@ - (void)setMirror:(BOOL)mirror { if (_mirror != mirror) { _mirror = mirror; -#if !TARGET_OS_OSX - [self setNeedsLayout]; -#else - self.needsLayout = YES; -#endif + self.videoView.transform = mirror ? CGAffineTransformMakeScale(-1.0, 1.0) : CGAffineTransformIdentity; } } @@ -246,14 +170,16 @@ - (void)setMirror:(BOOL)mirror { * @param objectFit The value to set on the {@code objectFit} property of this * {@code RTCVideoView}. */ -- (void)setObjectFit:(RTCVideoViewObjectFit)objectFit { - if (_objectFit != objectFit) { - _objectFit = objectFit; +- (void)setObjectFit:(RTCVideoViewObjectFit)fit { + if (_objectFit != fit) { + _objectFit = fit; #if !TARGET_OS_OSX - [self setNeedsLayout]; -#else - self.needsLayout = YES; + if (fit == RTCVideoViewObjectFitCover) { + self.videoView.videoContentMode = UIViewContentModeScaleAspectFill; + } else { + self.videoView.videoContentMode = UIViewContentModeScaleAspectFit; + } #endif } } @@ -273,14 +199,6 @@ - (void)setVideoTrack:(RTCVideoTrack *)videoTrack { dispatch_async(_module.workerQueue, ^{ [oldValue removeRenderer:self.videoView]; }); - _videoSize.height = 0; - _videoSize.width = 0; - -#if !TARGET_OS_OSX - [self setNeedsLayout]; -#else - self.needsLayout = YES; -#endif } _videoTrack = videoTrack; @@ -319,12 +237,7 @@ - (void)setVideoTrack:(RTCVideoTrack *)videoTrack { CVPixelBufferRelease(pixelBuffer); } - // XXX This RTCVideoView strongly retains its videoTrack. The latter - // strongly retains the former as well though because RTCVideoTrack strongly - // retains the RTCVideoRenderers added to it. In other words, there is a - // cycle of strong retainments and, consequently, there is a memory leak. In - // order to break the cycle, have this RTCVideoView as the RTCVideoRenderer - // of its videoTrack only while this view resides in a window. + // See "didMoveToWindow" above. if (videoTrack && self.window) { dispatch_async(_module.workerQueue, ^{ [videoTrack addRenderer:self.videoView]; @@ -333,46 +246,20 @@ - (void)setVideoTrack:(RTCVideoTrack *)videoTrack { } } -#pragma mark - RTCVideoViewDelegate methods - -/** - * Notifies this {@link RTCVideoViewDelegate} that a specific - * {@link RTCVideoRenderer} had the size of the video (frames) it renders - * changed. - * - * @param videoView The {@code RTCVideoRenderer} which had the size of the video - * (frames) it renders changed to the specified size. - * @param size The new size of the video (frames) to be rendered by the - * specified {@code videoView}. - */ -- (void)videoView:(id)videoView didChangeVideoSize:(CGSize)size { - if (videoView == self.videoView) { - _videoSize = size; - -#if !TARGET_OS_OSX - [self setNeedsLayout]; -#else - self.needsLayout = YES; -#endif - } -} - @end @implementation RTCVideoViewManager RCT_EXPORT_MODULE() -#if !TARGET_OS_OSX -- (UIView *)view { -#else +#if TARGET_OS_OSX - (NSView *)view { +#else +- (UIView *)view { #endif RTCVideoView *v = [[RTCVideoView alloc] init]; v.module = [self.bridge moduleForName:@"WebRTCModule"]; -#if !TARGET_OS_OSX v.clipsToBounds = YES; -#endif return v; } @@ -380,6 +267,8 @@ - (dispatch_queue_t)methodQueue { return dispatch_get_main_queue(); } +#pragma mark - View properties + RCT_EXPORT_VIEW_PROPERTY(mirror, BOOL) /** @@ -389,11 +278,11 @@ - (dispatch_queue_t)methodQueue { * the CSS style {@code object-fit}. */ RCT_CUSTOM_VIEW_PROPERTY(objectFit, NSString *, RTCVideoView) { - NSString *s = [RCTConvert NSString:json]; - RTCVideoViewObjectFit e = - (s && [s isEqualToString:@"cover"]) ? RTCVideoViewObjectFitCover : RTCVideoViewObjectFitContain; + NSString *fitStr = json; + RTCVideoViewObjectFit fit = + (fitStr && [fitStr isEqualToString:@"cover"]) ? RTCVideoViewObjectFitCover : RTCVideoViewObjectFitContain; - view.objectFit = e; + view.objectFit = fit; } RCT_CUSTOM_VIEW_PROPERTY(streamURL, NSString *, RTCVideoView) { @@ -402,7 +291,7 @@ - (dispatch_queue_t)methodQueue { return; } - NSString *streamReactTag = (NSString *)json; + NSString *streamReactTag = json; WebRTCModule *module = view.module; dispatch_async(module.workerQueue, ^{ diff --git a/ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m b/ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m index 4f559f8e7..ccf35b3e8 100644 --- a/ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m +++ b/ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m @@ -263,7 +263,7 @@ - (RTCVideoTrack *)createScreenCaptureVideoTrack { #else NSMutableArray *devices = [NSMutableArray array]; AVCaptureDeviceDiscoverySession *videoevicesSession = - [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:@[ AVCaptureDeviceTypeBuiltInWideAngleCamera ] + [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:@[ AVCaptureDeviceTypeBuiltInWideAngleCamera, AVCaptureDeviceTypeBuiltInUltraWideCamera, AVCaptureDeviceTypeBuiltInTelephotoCamera, AVCaptureDeviceTypeBuiltInDualCamera, AVCaptureDeviceTypeBuiltInDualWideCamera, AVCaptureDeviceTypeBuiltInTripleCamera] mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionUnspecified]; for (AVCaptureDevice *device in videoevicesSession.devices) { diff --git a/ios/RCTWebRTC/WebRTCModule+Transceivers.m b/ios/RCTWebRTC/WebRTCModule+Transceivers.m index b836efc49..75699de59 100644 --- a/ios/RCTWebRTC/WebRTCModule+Transceivers.m +++ b/ios/RCTWebRTC/WebRTCModule+Transceivers.m @@ -17,14 +17,7 @@ @implementation WebRTCModule (Transceivers) __block id params; dispatch_sync(self.workerQueue, ^{ - RTCRtpMediaType mediaType = RTCRtpMediaTypeUnsupported; - if ([kind isEqual:@"audio"]) { - mediaType = RTCRtpMediaTypeAudio; - } else if ([kind isEqual:@"video"]) { - mediaType = RTCRtpMediaTypeVideo; - } - - RTCRtpCapabilities *capabilities = [self.peerConnectionFactory rtpSenderCapabilitiesFor:mediaType]; + RTCRtpCapabilities *capabilities = [self.peerConnectionFactory rtpSenderCapabilitiesForKind:kind]; params = [SerializeUtils capabilitiesToJSON:capabilities]; }); @@ -35,14 +28,7 @@ @implementation WebRTCModule (Transceivers) __block id params; dispatch_sync(self.workerQueue, ^{ - RTCRtpMediaType mediaType = RTCRtpMediaTypeUnsupported; - if ([kind isEqual:@"audio"]) { - mediaType = RTCRtpMediaTypeAudio; - } else if ([kind isEqual:@"video"]) { - mediaType = RTCRtpMediaTypeVideo; - } - - RTCRtpCapabilities *capabilities = [self.peerConnectionFactory rtpSenderCapabilitiesFor:mediaType]; + RTCRtpCapabilities *capabilities = [self.peerConnectionFactory rtpReceiverCapabilitiesForKind:kind]; params = [SerializeUtils capabilitiesToJSON:capabilities]; }); @@ -213,8 +199,9 @@ @implementation WebRTCModule (Transceivers) // Get the available codecs RTCRtpTransceiverDirection direction = transceiver.direction; NSMutableArray *availableCodecs = [NSMutableArray new]; + NSString *kind = transceiver.mediaType == RTCRtpMediaTypeAudio ? @"audio" : @"video"; if (direction == RTCRtpTransceiverDirectionSendRecv || direction == RTCRtpTransceiverDirectionSendOnly) { - RTCRtpCapabilities *capabilities = [self.peerConnectionFactory rtpSenderCapabilitiesFor:transceiver.mediaType]; + RTCRtpCapabilities *capabilities = [self.peerConnectionFactory rtpSenderCapabilitiesForKind:kind]; for (RTCRtpCodecCapability *codec in capabilities.codecs) { NSDictionary *codecDict = [SerializeUtils codecCapabilityToJSON:codec]; [availableCodecs addObject:@{ @@ -224,8 +211,7 @@ @implementation WebRTCModule (Transceivers) } } if (direction == RTCRtpTransceiverDirectionSendRecv || direction == RTCRtpTransceiverDirectionRecvOnly) { - RTCRtpCapabilities *capabilities = - [self.peerConnectionFactory rtpReceiverCapabilitiesFor:transceiver.mediaType]; + RTCRtpCapabilities *capabilities = [self.peerConnectionFactory rtpReceiverCapabilitiesForKind:kind]; for (RTCRtpCodecCapability *codec in capabilities.codecs) { NSDictionary *codecDict = [SerializeUtils codecCapabilityToJSON:codec]; [availableCodecs addObject:@{ diff --git a/livekit-react-native-webrtc.podspec b/livekit-react-native-webrtc.podspec index aec23ac35..775d8699b 100644 --- a/livekit-react-native-webrtc.podspec +++ b/livekit-react-native-webrtc.podspec @@ -19,5 +19,5 @@ Pod::Spec.new do |s| s.libraries = 'c', 'sqlite3', 'stdc++' s.framework = 'AudioToolbox','AVFoundation', 'CoreAudio', 'CoreGraphics', 'CoreVideo', 'GLKit', 'VideoToolbox' s.dependency 'React-Core' - s.dependency 'WebRTC-SDK', '~>114.5735.10' + s.dependency 'WebRTC-SDK', '~>125.6422.02' end diff --git a/package-lock.json b/package-lock.json index 6b6614b47..c5539115b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@livekit/react-native-webrtc", - "version": "114.1.5", + "version": "125.0.0-beta.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@livekit/react-native-webrtc", - "version": "114.1.5", + "version": "125.0.0-beta.0", "license": "MIT", "dependencies": { "base64-js": "1.5.1", @@ -2496,12 +2496,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -3468,9 +3468,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -7627,12 +7627,12 @@ } }, "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "requires": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" } }, "browserslist": { @@ -8379,9 +8379,9 @@ } }, "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "requires": { "to-regex-range": "^5.0.1" diff --git a/package.json b/package.json index 33b27846b..294df993f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@livekit/react-native-webrtc", - "version": "114.1.5", + "version": "125.0.0-beta.0", "repository": { "type": "git", "url": "git+https://github.com/livekit/react-native-webrtc.git" diff --git a/src/RTCIceCandidate.ts b/src/RTCIceCandidate.ts index 532985417..e935cc45f 100644 --- a/src/RTCIceCandidate.ts +++ b/src/RTCIceCandidate.ts @@ -6,12 +6,12 @@ interface RTCIceCandidateInfo { export default class RTCIceCandidate { candidate: string; - sdpMLineIndex: number; - sdpMid: string; + sdpMLineIndex?: number | null; + sdpMid?: string | null; constructor({ candidate = '', sdpMLineIndex = null, sdpMid = null }: RTCIceCandidateInfo) { - if (sdpMLineIndex === null || sdpMid === null) { - throw new TypeError('`sdpMLineIndex` and `sdpMid` must not null'); + if (sdpMLineIndex === null && sdpMid === null) { + throw new TypeError('`sdpMLineIndex` and `sdpMid` must not be both null'); } this.candidate = candidate; diff --git a/src/RTCPeerConnection.ts b/src/RTCPeerConnection.ts index 4b720a8f8..172ca0018 100644 --- a/src/RTCPeerConnection.ts +++ b/src/RTCPeerConnection.ts @@ -332,13 +332,12 @@ export default class RTCPeerConnection extends EventTarget Date: Mon, 24 Jun 2024 14:22:11 +0900 Subject: [PATCH 016/144] release 125.0.0 2d153e1 Merge upstream and update webrtc to M125 (#9) ( davidliu 2024-06-24 11:20:10 +0900) --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index c5539115b..25bf12cd7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@livekit/react-native-webrtc", - "version": "125.0.0-beta.0", + "version": "125.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@livekit/react-native-webrtc", - "version": "125.0.0-beta.0", + "version": "125.0.0", "license": "MIT", "dependencies": { "base64-js": "1.5.1", diff --git a/package.json b/package.json index 294df993f..e26a3bba6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@livekit/react-native-webrtc", - "version": "125.0.0-beta.0", + "version": "125.0.0", "repository": { "type": "git", "url": "git+https://github.com/livekit/react-native-webrtc.git" From e0740f06f272514fa9567170d9c58f9a356f5670 Mon Sep 17 00:00:00 2001 From: davidliu Date: Mon, 24 Jun 2024 14:30:17 +0900 Subject: [PATCH 017/144] Update README.md to avoid confusion with the original --- README.md | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index abd0f0ab0..7f4b788d1 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,18 @@ [React Native WebRTC](https://github.com/react-native-webrtc/react-native-webrtc) -# React-Native-WebRTC - -[![npm version](https://img.shields.io/npm/v/react-native-webrtc)](https://www.npmjs.com/package/react-native-webrtc) -[![npm downloads](https://img.shields.io/npm/dm/react-native-webrtc)](https://www.npmjs.com/package/react-native-webrtc) +# React-Native-WebRTC for LiveKit +https://img.shields.io/npm/v/@livekit/react-native-webrtc +[![npm version](https://img.shields.io/npm/v/@livekit/react-native-webrtc)](https://www.npmjs.com/package/@livekit/react-native-webrtc) [![Discourse topics](https://img.shields.io/discourse/topics?server=https%3A%2F%2Freact-native-webrtc.discourse.group%2F)](https://react-native-webrtc.discourse.group/) A WebRTC module for React Native. +> [!NOTE] +> This is a fork of the original [react-native-webrtc](https://github.com/react-native-webrtc/react-native-webrtc) repo, with different underlying WebRTC fork. +> This module is primarily to be used in conjunction with the [LiveKit React Native SDK](https://github.com/livekit/client-sdk-react-native), and shouldn't be used independently. +> +> Developers looking to add WebRTC without LiveKit functionality to their React Native projects should use the original module instead. + ## Feature Overview | | Android | iOS | tvOS | macOS* | Windows* | Web* | Expo* | @@ -51,9 +56,9 @@ Software encode/decode factories have been enabled by default. Use one of the following preferred package install methods to immediately get going. Don't forget to follow platform guides below to cover any extra required steps. -**npm:** `npm install react-native-webrtc --save` -**yarn:** `yarn add react-native-webrtc` -**pnpm:** `pnpm install react-native-webrtc` +**npm:** `npm install @livekit/react-native-webrtc --save` +**yarn:** `yarn add @livekit/react-native-webrtc` +**pnpm:** `pnpm install @livekit/react-native-webrtc` ## Guides From 6986a6e7f5e59cad0aa30e169a0c06f865b4b58f Mon Sep 17 00:00:00 2001 From: davidliu Date: Mon, 24 Jun 2024 14:30:33 +0900 Subject: [PATCH 018/144] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 7f4b788d1..ff88912af 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ [React Native WebRTC](https://github.com/react-native-webrtc/react-native-webrtc) # React-Native-WebRTC for LiveKit -https://img.shields.io/npm/v/@livekit/react-native-webrtc [![npm version](https://img.shields.io/npm/v/@livekit/react-native-webrtc)](https://www.npmjs.com/package/@livekit/react-native-webrtc) [![Discourse topics](https://img.shields.io/discourse/topics?server=https%3A%2F%2Freact-native-webrtc.discourse.group%2F)](https://react-native-webrtc.discourse.group/) From 774f39e0a463aea4bcde2fd4c54858858ca1d783 Mon Sep 17 00:00:00 2001 From: davidliu Date: Tue, 25 Jun 2024 19:37:49 +0900 Subject: [PATCH 019/144] android: declare a dependency on androidx.core 1.7.0 --- android/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/android/build.gradle b/android/build.gradle index eaf3d982e..b50d257c9 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -31,4 +31,5 @@ android { dependencies { implementation 'com.facebook.react:react-native:+' api 'io.github.webrtc-sdk:android:125.6422.02' + implementation "androidx.core:core:1.7.0" } From 49af0ad232e58ad1423d0144253961da3ee22fbb Mon Sep 17 00:00:00 2001 From: davidliu Date: Fri, 26 Jul 2024 14:22:57 +0900 Subject: [PATCH 020/144] ios: Add audioProcessingModule to WebRTCModuleOptions (#13) --- ios/RCTWebRTC/WebRTCModule.m | 19 ++++++++++++++++--- ios/RCTWebRTC/WebRTCModuleOptions.h | 1 + 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/ios/RCTWebRTC/WebRTCModule.m b/ios/RCTWebRTC/WebRTCModule.m index 93ff75097..6917aee12 100644 --- a/ios/RCTWebRTC/WebRTCModule.m +++ b/ios/RCTWebRTC/WebRTCModule.m @@ -43,6 +43,7 @@ - (instancetype)init { id audioDevice = options.audioDevice; id decoderFactory = options.videoDecoderFactory; id encoderFactory = options.videoEncoderFactory; + id audioProcessingModule = options.audioProcessingModule; NSDictionary *fieldTrials = options.fieldTrials; RTCLoggingSeverity loggingSeverity = options.loggingSeverity; @@ -69,9 +70,21 @@ - (instancetype)init { RCTLogInfo(@"Using video encoder factory: %@", NSStringFromClass([encoderFactory class])); RCTLogInfo(@"Using video decoder factory: %@", NSStringFromClass([decoderFactory class])); - _peerConnectionFactory = [[RTCPeerConnectionFactory alloc] initWithEncoderFactory:encoderFactory - decoderFactory:decoderFactory - audioDevice:audioDevice]; + if (audioProcessingModule != nil) { + if (audioDevice != nil) { + NSLog(@"Both audioProcessingModule and audioDevice are provided, but only one can be used. Ignoring audioDevice."); + } + RCTLogInfo(@"Using audio processing module: %@", NSStringFromClass([audioProcessingModule class])); + _peerConnectionFactory = [[RTCPeerConnectionFactory alloc] initWithBypassVoiceProcessing:NO + encoderFactory:encoderFactory + decoderFactory:decoderFactory + audioProcessingModule:audioProcessingModule]; + } else { + RCTLogInfo(@"Using audio device: %@", NSStringFromClass([audioDevice class])); + _peerConnectionFactory = [[RTCPeerConnectionFactory alloc] initWithEncoderFactory:encoderFactory + decoderFactory:decoderFactory + audioDevice:audioDevice]; + } _peerConnections = [NSMutableDictionary new]; _localStreams = [NSMutableDictionary new]; diff --git a/ios/RCTWebRTC/WebRTCModuleOptions.h b/ios/RCTWebRTC/WebRTCModuleOptions.h index 7c91b36e8..6904736fa 100644 --- a/ios/RCTWebRTC/WebRTCModuleOptions.h +++ b/ios/RCTWebRTC/WebRTCModuleOptions.h @@ -8,6 +8,7 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, strong, nullable) id videoDecoderFactory; @property(nonatomic, strong, nullable) id videoEncoderFactory; @property(nonatomic, strong, nullable) id audioDevice; +@property(nonatomic, strong, nullable) id audioProcessingModule; @property(nonatomic, strong, nullable) NSDictionary *fieldTrials; @property(nonatomic, assign) RTCLoggingSeverity loggingSeverity; From 4d19ccd0aed2113d5c363e388702b0f44d50ad0b Mon Sep 17 00:00:00 2001 From: davidliu Date: Fri, 26 Jul 2024 14:27:13 +0900 Subject: [PATCH 021/144] release 125.0.1 49af0ad ios: Add audioProcessingModule to WebRTCModuleOptions (#13) ( davidliu 2024-07-26 14:22:57 +0900) 774f39e android: declare a dependency on androidx.core 1.7.0 ( davidliu 2024-06-25 19:37:49 +0900) 6986a6e Update README.md ( davidliu 2024-06-24 14:30:33 +0900) e0740f0 Update README.md to avoid confusion with the original ( davidliu 2024-06-24 14:30:17 +0900) --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 25bf12cd7..5f5636f30 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@livekit/react-native-webrtc", - "version": "125.0.0", + "version": "125.0.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@livekit/react-native-webrtc", - "version": "125.0.0", + "version": "125.0.1", "license": "MIT", "dependencies": { "base64-js": "1.5.1", diff --git a/package.json b/package.json index e26a3bba6..89170402e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@livekit/react-native-webrtc", - "version": "125.0.0", + "version": "125.0.1", "repository": { "type": "git", "url": "git+https://github.com/livekit/react-native-webrtc.git" From ffd5936acfdb688cc8dcff034745b9a010eb9801 Mon Sep 17 00:00:00 2001 From: davidliu Date: Mon, 5 Aug 2024 00:25:40 +0900 Subject: [PATCH 022/144] android,ios: update webrtc to 125.0.4 --- android/build.gradle | 2 +- livekit-react-native-webrtc.podspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index b50d257c9..6bc6fb712 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -30,6 +30,6 @@ android { dependencies { implementation 'com.facebook.react:react-native:+' - api 'io.github.webrtc-sdk:android:125.6422.02' + api 'io.github.webrtc-sdk:android:125.6422.04' implementation "androidx.core:core:1.7.0" } diff --git a/livekit-react-native-webrtc.podspec b/livekit-react-native-webrtc.podspec index 775d8699b..6994432d1 100644 --- a/livekit-react-native-webrtc.podspec +++ b/livekit-react-native-webrtc.podspec @@ -19,5 +19,5 @@ Pod::Spec.new do |s| s.libraries = 'c', 'sqlite3', 'stdc++' s.framework = 'AudioToolbox','AVFoundation', 'CoreAudio', 'CoreGraphics', 'CoreVideo', 'GLKit', 'VideoToolbox' s.dependency 'React-Core' - s.dependency 'WebRTC-SDK', '~>125.6422.02' + s.dependency 'WebRTC-SDK', '~>125.6422.04' end From 7472d2dce416476ebdc269111277c5b57da2c617 Mon Sep 17 00:00:00 2001 From: davidliu Date: Mon, 5 Aug 2024 00:26:35 +0900 Subject: [PATCH 023/144] release 125.0.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ffd5936 android,ios: update webrtc to 125.0.4 ( davidliu 2024-08-05 00:25:40 +0900) 09f609b release 124.0.3 ( Saúl Ibarra Corretgé 2024-07-08 10:43:08 +0200) 3e11c99 misc: ignore Android build files when releasing to npm ( Saúl Ibarra Corretgé 2024-07-08 10:42:23 +0200) a45efdc release 124.0.2 ( Saúl Ibarra Corretgé 2024-07-08 10:39:16 +0200) 160ece9 ios: fix compatibility with RN >= 0.73 ( Saúl Ibarra Corretgé 2024-06-27 23:04:49 +0200) 5fdb6ad android: declare dependency on androidx.core 1.7.0 (#1586) ( davidliu 2024-06-26 00:30:02 +0900) 0a36e9d android: release audio manager module after creating factory ( davidliu 2024-06-21 22:04:45 +0900) 54b5607 build(deps-dev): bump braces from 3.0.2 to 3.0.3 (#1578) ( dependabot[bot] 2024-06-13 17:59:14 +0800) 232fc06 release 124.0.1 ( Saúl Ibarra Corretgé 2024-06-13 10:45:44 +0200) 20cf1d5 preserve order ( Burak KIYAK 2024-05-03 13:41:59 +0200) 64e8298 ios: add all available camera device types ( Burak KIYAK 2024-04-30 12:30:38 +0200) f36b6b8 ios: refactor rendering in RTCVideoView ( Saúl Ibarra Corretgé 2024-06-11 09:35:36 +0200) bbd903c api: allow sdpMid / sdpLineIndex to be null in RTCIceCandidate ( omerts 2024-06-04 14:42:40 +0300) ff6110e webrtc: update WebRTC to M124 ( Saúl Ibarra Corretgé 2024-06-03 14:33:18 +0200) --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5f5636f30..cfd2664e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@livekit/react-native-webrtc", - "version": "125.0.1", + "version": "125.0.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@livekit/react-native-webrtc", - "version": "125.0.1", + "version": "125.0.2", "license": "MIT", "dependencies": { "base64-js": "1.5.1", diff --git a/package.json b/package.json index 89170402e..a0b407cf1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@livekit/react-native-webrtc", - "version": "125.0.1", + "version": "125.0.2", "repository": { "type": "git", "url": "git+https://github.com/livekit/react-native-webrtc.git" From 1121257e74aeb6897be7c850735eb59dc4b0e481 Mon Sep 17 00:00:00 2001 From: davidliu Date: Mon, 5 Aug 2024 14:30:17 +0900 Subject: [PATCH 024/144] ci: fix ios compile (#14) --- .../GumTestApp/ios/GumTestApp.xcodeproj/project.pbxproj | 6 +++--- examples/GumTestApp/ios/Podfile | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/GumTestApp/ios/GumTestApp.xcodeproj/project.pbxproj b/examples/GumTestApp/ios/GumTestApp.xcodeproj/project.pbxproj index 6d072ddce..90418cb29 100644 --- a/examples/GumTestApp/ios/GumTestApp.xcodeproj/project.pbxproj +++ b/examples/GumTestApp/ios/GumTestApp.xcodeproj/project.pbxproj @@ -277,7 +277,7 @@ TestTargetID = 13B07F861A680F5B00A75B9A; }; 13B07F861A680F5B00A75B9A = { - DevelopmentTeam = AJT772J42H; + DevelopmentTeam = 76TVFCUKK7; LastSwiftMigration = 1120; }; 2D02E47A1E0B4A5D006451C7 = { @@ -636,7 +636,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = AJT772J42H; + DEVELOPMENT_TEAM = 76TVFCUKK7; ENABLE_BITCODE = NO; INFOPLIST_FILE = GumTestApp/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -660,7 +660,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = AJT772J42H; + DEVELOPMENT_TEAM = 76TVFCUKK7; INFOPLIST_FILE = GumTestApp/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_LDFLAGS = ( diff --git a/examples/GumTestApp/ios/Podfile b/examples/GumTestApp/ios/Podfile index d52ad8f37..58bd8b13f 100644 --- a/examples/GumTestApp/ios/Podfile +++ b/examples/GumTestApp/ios/Podfile @@ -13,7 +13,7 @@ prepare_react_native_project! # dependencies: { # ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}), # ``` -flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled +flipper_config = FlipperConfiguration.disabled linkage = ENV['USE_FRAMEWORKS'] if linkage != nil From c10087e5d0f0751836432b7cf93318509657f76f Mon Sep 17 00:00:00 2001 From: davidliu Date: Mon, 19 Aug 2024 14:45:18 +0900 Subject: [PATCH 025/144] Merge upstream 124.0.4 into master (#16) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ios: add support for external cameras on iPad * ci: remove flipper from gumtestapp (#1608) These were causing build errors recently, and were generally unneeded anyways. * pc: align createDataChannel with standard - Throw TypeError if no argument passed - Stringify the label Fixes: https://github.com/react-native-webrtc/react-native-webrtc/issues/1605 * android: report actual size in camera MediaStreamTrack settings (#1598) * ios: fix exception in iOS 17+ w/ Xcode 15.4 * android: remove no longer used replace rule from manifest (#1609) * sender: fix serializing RTCRtpSendParameters It's possible for user code to replace encodings entirely. Thus, the resulting array will not have RTCRtpEncodingParameters object instances, but plain objects. Handle it by deep-cloning the objects with JSON.parse(JSON.stringify(x)) since that will take care of appropriately serializing them, no matter the type. * misc: make serialization more resilient Don't directly call toJSON, but rather rely on JSON serialization to do it when cloning. * release 124.0.4 89557ca misc: make serialization more resilient ( Saúl Ibarra Corretgé 2024-08-14 11:53:32 +0200) 6cfedd7 sender: fix serializing RTCRtpSendParameters ( Saúl Ibarra Corretgé 2024-08-14 11:11:08 +0200) ac7f578 android: remove no longer used replace rule from manifest (#1609) ( Saúl Ibarra Corretgé 2024-08-07 17:17:03 +0200) f6667c8 ios: fix exception in iOS 17+ w/ Xcode 15.4 ( mtdxc 2024-08-07 17:22:10 +0800) 4c34ae1 android: report actual size in camera MediaStreamTrack settings (#1598) ( davidliu 2024-08-07 17:56:57 +0900) fb02a5b pc: align createDataChannel with standard ( Saúl Ibarra Corretgé 2024-08-06 15:28:24 +0200) c0ddefd ci: remove flipper from gumtestapp (#1608) ( davidliu 2024-08-07 16:00:01 +0900) a1bb18a ios: add support for external cameras on iPad ( mtdxc 2024-07-10 20:25:23 +0800) * ios: Add RTCAudioSession helper methods needed for CallKit (#1614) * Fix package name references --------- Co-authored-by: mtdxc Co-authored-by: Saúl Ibarra Corretgé Co-authored-by: Saúl Ibarra Corretgé --- Documentation/iOSInstallation.md | 29 +++++++++- Documentation/tvOSInstallation.md | 2 +- android/src/main/AndroidManifest.xml | 5 -- .../AbstractVideoCaptureController.java | 27 +++++---- .../WebRTCModule/CameraCaptureController.java | 51 ++++++++++++++--- .../oney/WebRTCModule/GetUserMediaImpl.java | 2 +- .../WebRTCModule/ScreenCaptureController.java | 6 +- .../main/java/org/webrtc/Camera1Helper.java | 55 +++++++++++++++++++ .../main/java/org/webrtc/Camera2Helper.java | 51 +++++++++++++++++ examples/GumTestApp_macOS/App.js | 2 +- examples/GumTestApp_macOS/package.json | 2 +- ios/RCTWebRTC.xcodeproj/project.pbxproj | 4 ++ ios/RCTWebRTC/WebRTCModule+RTCAudioSession.m | 20 +++++++ ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m | 8 ++- src/RTCAudioSession.ts | 25 +++++++++ src/RTCPeerConnection.ts | 8 ++- src/RTCRtpParameters.ts | 11 ++-- src/RTCRtpSendParameters.ts | 10 ++-- src/index.ts | 2 + 19 files changed, 276 insertions(+), 44 deletions(-) create mode 100644 android/src/main/java/org/webrtc/Camera1Helper.java create mode 100644 android/src/main/java/org/webrtc/Camera2Helper.java create mode 100644 ios/RCTWebRTC/WebRTCModule+RTCAudioSession.m create mode 100644 src/RTCAudioSession.ts diff --git a/Documentation/iOSInstallation.md b/Documentation/iOSInstallation.md index eb98961b0..e8d548fa1 100644 --- a/Documentation/iOSInstallation.md +++ b/Documentation/iOSInstallation.md @@ -8,7 +8,7 @@ See a sample app in the `examples/GumTestApp` directory. **IMPORTANT:** Make sure you are using CocoaPods 1.10 or higher. You may have to change the `platform` field in your podfile. -`react-native-webrtc` doesn't support iOS < 12 +`@livekit/react-native-webrtc` doesn't support iOS < 12 Set it to '12.0' or above or you'll get an error when running `pod install`. ``` @@ -26,6 +26,33 @@ Navigate to `/ios//` and edit `Info.plist`, add the Microphone permission description ``` +## CallKit + +If your app uses a CallKit integration to handle incoming calls, then your +CXProviderDelegate should call through to `RTCAudioSession.sharedInstance.audioSessionDidActivate/Deactivate` accordingly. + +``` +#import + +- (void) provider:(CXProvider *) provider didActivateAudioSession:(AVAudioSession *) audioSession { + [[RTCAudioSession sharedInstance] audioSessionDidActivate:[AVAudioSession sharedInstance]]; +} + +- (void) provider:(CXProvider *) provider didDeactivateAudioSession:(AVAudioSession *) audioSession { + [[RTCAudioSession sharedInstance] audioSessionDidDeactivate:[AVAudioSession sharedInstance]]; +} +``` + +Javascript methods are also provided to call these methods: + +``` +import { RTCAudioSession } from '@livekit/react-native-webrtc' + +// Call as needed. +RTCAudioSession.audioSessionDidActivate(); +RTCAudioSession.audioSessionDidDeactivate(); +``` + ## Library not loaded/Code signature invalid This is an issue with iOS 13.3.1. diff --git a/Documentation/tvOSInstallation.md b/Documentation/tvOSInstallation.md index e541f29d2..ddb3c11ad 100644 --- a/Documentation/tvOSInstallation.md +++ b/Documentation/tvOSInstallation.md @@ -13,7 +13,7 @@ Change the following dependency in your projects `package.json` file to get star **IMPORTANT:** Make sure you are using CocoaPods 1.10 or higher. You may have to change the `platform` field in your podfile. -`react-native-webrtc` doesn't support tvOS < 16. Set it to '16.0' or above. +`@livekit/react-native-webrtc` doesn't support tvOS < 16. Set it to '16.0' or above. Older versions of tvOS don't support WebRTC. ``` diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 14fe4a945..321315114 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -8,9 +8,4 @@ android:foregroundServiceType="mediaProjection"> - diff --git a/android/src/main/java/com/oney/WebRTCModule/AbstractVideoCaptureController.java b/android/src/main/java/com/oney/WebRTCModule/AbstractVideoCaptureController.java index 393f73c51..bffb99798 100644 --- a/android/src/main/java/com/oney/WebRTCModule/AbstractVideoCaptureController.java +++ b/android/src/main/java/com/oney/WebRTCModule/AbstractVideoCaptureController.java @@ -3,9 +3,13 @@ import org.webrtc.VideoCapturer; public abstract class AbstractVideoCaptureController { - protected int width; - protected int height; - private final int fps; + protected final int targetWidth; + protected final int targetHeight; + protected final int targetFps; + + protected int actualWidth; + protected int actualHeight; + protected int actualFps; /** * {@link VideoCapturer} which this controller manages. @@ -15,9 +19,12 @@ public abstract class AbstractVideoCaptureController { protected CapturerEventsListener capturerEventsListener; public AbstractVideoCaptureController(int width, int height, int fps) { - this.width = width; - this.height = height; - this.fps = fps; + this.targetWidth = width; + this.targetHeight = height; + this.targetFps = fps; + this.actualWidth = width; + this.actualHeight = height; + this.actualFps = fps; } public void initializeVideoCapturer() { @@ -32,15 +39,15 @@ public void dispose() { } public int getHeight() { - return height; + return actualHeight; } public int getWidth() { - return width; + return actualWidth; } public int getFrameRate() { - return fps; + return actualFps; } public VideoCapturer getVideoCapturer() { @@ -49,7 +56,7 @@ public VideoCapturer getVideoCapturer() { public void startCapture() { try { - videoCapturer.startCapture(width, height, fps); + videoCapturer.startCapture(targetWidth, targetHeight, targetFps); } catch (RuntimeException e) { // XXX This can only fail if we initialize the capturer incorrectly, // which we don't. Thus, ignore any failures here since we trust diff --git a/android/src/main/java/com/oney/WebRTCModule/CameraCaptureController.java b/android/src/main/java/com/oney/WebRTCModule/CameraCaptureController.java index 0faff5d44..4e93b4cc0 100644 --- a/android/src/main/java/com/oney/WebRTCModule/CameraCaptureController.java +++ b/android/src/main/java/com/oney/WebRTCModule/CameraCaptureController.java @@ -1,11 +1,20 @@ package com.oney.WebRTCModule; +import android.content.Context; +import android.hardware.camera2.CameraManager; import android.util.Log; +import android.util.Pair; +import androidx.annotation.Nullable; import com.facebook.react.bridge.ReadableMap; +import org.webrtc.Camera1Capturer; +import org.webrtc.Camera1Helper; +import org.webrtc.Camera2Capturer; +import org.webrtc.Camera2Helper; import org.webrtc.CameraEnumerator; import org.webrtc.CameraVideoCapturer; +import org.webrtc.Size; import org.webrtc.VideoCapturer; import java.util.ArrayList; @@ -19,6 +28,7 @@ public class CameraCaptureController extends AbstractVideoCaptureController { private boolean isFrontFacing; + private final Context context; private final CameraEnumerator cameraEnumerator; private final ReadableMap constraints; @@ -30,9 +40,10 @@ public class CameraCaptureController extends AbstractVideoCaptureController { */ private final CameraEventsHandler cameraEventsHandler = new CameraEventsHandler(); - public CameraCaptureController(CameraEnumerator cameraEnumerator, ReadableMap constraints) { + public CameraCaptureController(Context context, CameraEnumerator cameraEnumerator, ReadableMap constraints) { super(constraints.getInt("width"), constraints.getInt("height"), constraints.getInt("frameRate")); + this.context = context; this.cameraEnumerator = cameraEnumerator; this.constraints = constraints; } @@ -75,7 +86,30 @@ protected VideoCapturer createVideoCapturer() { String deviceId = ReactBridgeUtil.getMapStrValue(this.constraints, "deviceId"); String facingMode = ReactBridgeUtil.getMapStrValue(this.constraints, "facingMode"); - return createVideoCapturer(deviceId, facingMode); + Pair result = createVideoCapturer(deviceId, facingMode); + if(result == null) { + return null; + } + + String cameraName = result.first; + VideoCapturer videoCapturer = result.second; + + // Find actual capture format. + Size actualSize = null; + if (videoCapturer instanceof Camera1Capturer) { + int cameraId = Camera1Helper.getCameraId(cameraName); + actualSize = Camera1Helper.findClosestCaptureFormat(cameraId, targetWidth, targetHeight); + } else if (videoCapturer instanceof Camera2Capturer) { + CameraManager cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE); + actualSize = Camera2Helper.findClosestCaptureFormat(cameraManager, cameraName, targetWidth, targetHeight); + } + + if (actualSize != null) { + actualWidth = actualSize.width; + actualHeight = actualSize.height; + } + + return videoCapturer; } /** @@ -117,10 +151,11 @@ public void onCameraSwitchError(String s) { * @param facingMode the facing of the requested video source such as * {@code user} and {@code environment}. If {@code null}, "user" is * presumed. - * @return a {@code VideoCapturer} satisfying the {@code facingMode} or - * {@code deviceId} constraint + * @return a pair containing the deviceId and {@code VideoCapturer} satisfying the {@code facingMode} or + * {@code deviceId} constraint, or null. */ - private VideoCapturer createVideoCapturer(String deviceId, String facingMode) { + @Nullable + private Pair createVideoCapturer(String deviceId, String facingMode) { String[] deviceNames = cameraEnumerator.getDeviceNames(); List failedDevices = new ArrayList<>(); @@ -139,7 +174,7 @@ private VideoCapturer createVideoCapturer(String deviceId, String facingMode) { if (videoCapturer != null) { Log.d(TAG, message + " succeeded"); this.isFrontFacing = cameraEnumerator.isFrontFacing(cameraName); - return videoCapturer; + return new Pair(cameraName, videoCapturer); } else { // fallback to facingMode Log.d(TAG, message + " failed"); @@ -161,7 +196,7 @@ private VideoCapturer createVideoCapturer(String deviceId, String facingMode) { if (videoCapturer != null) { Log.d(TAG, message + " succeeded"); this.isFrontFacing = cameraEnumerator.isFrontFacing(name); - return videoCapturer; + return new Pair(name, videoCapturer); } else { Log.d(TAG, message + " failed"); failedDevices.add(name); @@ -176,7 +211,7 @@ private VideoCapturer createVideoCapturer(String deviceId, String facingMode) { if (videoCapturer != null) { Log.d(TAG, message + " succeeded"); this.isFrontFacing = cameraEnumerator.isFrontFacing(name); - return videoCapturer; + return new Pair(name, videoCapturer); } else { Log.d(TAG, message + " failed"); failedDevices.add(name); diff --git a/android/src/main/java/com/oney/WebRTCModule/GetUserMediaImpl.java b/android/src/main/java/com/oney/WebRTCModule/GetUserMediaImpl.java index 01df786c2..882b1183c 100644 --- a/android/src/main/java/com/oney/WebRTCModule/GetUserMediaImpl.java +++ b/android/src/main/java/com/oney/WebRTCModule/GetUserMediaImpl.java @@ -192,7 +192,7 @@ void getUserMedia(final ReadableMap constraints, final Callback successCallback, Log.d(TAG, "getUserMedia(video): " + videoConstraintsMap); CameraCaptureController cameraCaptureController = - new CameraCaptureController(getCameraEnumerator(), videoConstraintsMap); + new CameraCaptureController(reactContext.getCurrentActivity(), getCameraEnumerator(), videoConstraintsMap); videoTrack = createVideoTrack(cameraCaptureController); } diff --git a/android/src/main/java/com/oney/WebRTCModule/ScreenCaptureController.java b/android/src/main/java/com/oney/WebRTCModule/ScreenCaptureController.java index 9d50263cb..41b23aa96 100644 --- a/android/src/main/java/com/oney/WebRTCModule/ScreenCaptureController.java +++ b/android/src/main/java/com/oney/WebRTCModule/ScreenCaptureController.java @@ -41,9 +41,9 @@ public void onOrientationChanged(int orientation) { DisplayMetrics displayMetrics = DisplayUtils.getDisplayMetrics((Activity) context); final int width = displayMetrics.widthPixels; final int height = displayMetrics.heightPixels; - if (width != ScreenCaptureController.this.width || height != ScreenCaptureController.this.height) { - ScreenCaptureController.this.width = width; - ScreenCaptureController.this.height = height; + if (width != ScreenCaptureController.this.actualWidth || height != ScreenCaptureController.this.actualHeight) { + ScreenCaptureController.this.actualWidth = width; + ScreenCaptureController.this.actualHeight = height; // Pivot to the executor thread because videoCapturer.changeCaptureFormat runs in the main // thread and may deadlock. diff --git a/android/src/main/java/org/webrtc/Camera1Helper.java b/android/src/main/java/org/webrtc/Camera1Helper.java new file mode 100644 index 000000000..f0dec0d8d --- /dev/null +++ b/android/src/main/java/org/webrtc/Camera1Helper.java @@ -0,0 +1,55 @@ +/* + * Copyright 2023-2024 LiveKit, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 org.webrtc; + +import androidx.annotation.Nullable; + +import java.util.ArrayList; +import java.util.List; + +/** + * A helper to access package-protected methods used in [Camera2Session] + *

+ * Note: cameraId as used in the Camera1XXX classes refers to the index within the list of cameras. + * + * @suppress + */ + +public class Camera1Helper { + + public static int getCameraId(String deviceName) { + return Camera1Enumerator.getCameraIndex(deviceName); + } + + @Nullable + public static List getSupportedFormats(int cameraId) { + return Camera1Enumerator.getSupportedFormats(cameraId); + } + + public static Size findClosestCaptureFormat(int cameraId, int width, int height) { + List formats = getSupportedFormats(cameraId); + + List sizes = new ArrayList<>(); + if (formats != null) { + for (CameraEnumerationAndroid.CaptureFormat format : formats) { + sizes.add(new Size(format.width, format.height)); + } + } + + return CameraEnumerationAndroid.getClosestSupportedSize(sizes, width, height); + } +} diff --git a/android/src/main/java/org/webrtc/Camera2Helper.java b/android/src/main/java/org/webrtc/Camera2Helper.java new file mode 100644 index 000000000..eab20edb2 --- /dev/null +++ b/android/src/main/java/org/webrtc/Camera2Helper.java @@ -0,0 +1,51 @@ +/* + * Copyright 2023-2024 LiveKit, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 org.webrtc; + +import android.hardware.camera2.CameraManager; + +import androidx.annotation.Nullable; + +import java.util.ArrayList; +import java.util.List; + +/** + * A helper to access package-protected methods used in [Camera2Session] + *

+ * Note: cameraId as used in the Camera2XXX classes refers to the id returned + * by [CameraManager.getCameraIdList]. + */ +public class Camera2Helper { + + @Nullable + public static List getSupportedFormats(CameraManager cameraManager, @Nullable String cameraId) { + return Camera2Enumerator.getSupportedFormats(cameraManager, cameraId); + } + + public static Size findClosestCaptureFormat(CameraManager cameraManager, @Nullable String cameraId, int width, int height) { + List formats = getSupportedFormats(cameraManager, cameraId); + + List sizes = new ArrayList<>(); + if (formats != null) { + for (CameraEnumerationAndroid.CaptureFormat format : formats) { + sizes.add(new Size(format.width, format.height)); + } + } + + return CameraEnumerationAndroid.getClosestSupportedSize(sizes, width, height); + } +} diff --git a/examples/GumTestApp_macOS/App.js b/examples/GumTestApp_macOS/App.js index 8f0bd3609..00166df25 100644 --- a/examples/GumTestApp_macOS/App.js +++ b/examples/GumTestApp_macOS/App.js @@ -17,7 +17,7 @@ import { StatusBar, } from 'react-native'; import { Colors } from 'react-native/Libraries/NewAppScreen'; -import { mediaDevices, RTCView } from 'react-native-webrtc'; +import { mediaDevices, RTCView } from '@livekit/react-native-webrtc'; const App: () => React$Node = () => { const [stream, setStream] = useState(null); diff --git a/examples/GumTestApp_macOS/package.json b/examples/GumTestApp_macOS/package.json index 9cd663d17..97eabf563 100644 --- a/examples/GumTestApp_macOS/package.json +++ b/examples/GumTestApp_macOS/package.json @@ -15,7 +15,7 @@ "react": "16.11.0", "react-native": "0.62.0", "react-native-macos": "^0.62.16", - "react-native-webrtc": "*" + "@livekit/react-native-webrtc": "*" }, "devDependencies": { "@babel/core": "7.12.8", diff --git a/ios/RCTWebRTC.xcodeproj/project.pbxproj b/ios/RCTWebRTC.xcodeproj/project.pbxproj index 7c4e2bd7d..49e26d1ce 100644 --- a/ios/RCTWebRTC.xcodeproj/project.pbxproj +++ b/ios/RCTWebRTC.xcodeproj/project.pbxproj @@ -24,6 +24,7 @@ 4EE3A8D425B841DD00FAA24A /* ScreenCapturer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EE3A8CD25B841DD00FAA24A /* ScreenCapturer.m */; }; D3FF699919D2664B25C9D458 /* Pods_RCTWebRTC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A20F721AD842563B66292D5B /* Pods_RCTWebRTC.framework */; }; D74EF94829652169000742E1 /* TrackCapturerEventsEmitter.m in Sources */ = {isa = PBXBuildFile; fileRef = D74EF94629652169000742E1 /* TrackCapturerEventsEmitter.m */; }; + D7F0711E2C6DC91F0031F594 /* WebRTCModule+RTCAudioSession.m in Sources */ = {isa = PBXBuildFile; fileRef = D7F0711D2C6DC91F0031F594 /* WebRTCModule+RTCAudioSession.m */; }; DEC96577264176C10052DB35 /* DataChannelWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = DEC96576264176C10052DB35 /* DataChannelWrapper.m */; }; /* End PBXBuildFile section */ @@ -75,6 +76,7 @@ D74EF94529652148000742E1 /* CapturerEventsDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CapturerEventsDelegate.h; path = RCTWebRTC/CapturerEventsDelegate.h; sourceTree = SOURCE_ROOT; }; D74EF94629652169000742E1 /* TrackCapturerEventsEmitter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TrackCapturerEventsEmitter.m; path = RCTWebRTC/TrackCapturerEventsEmitter.m; sourceTree = SOURCE_ROOT; }; D74EF94729652169000742E1 /* TrackCapturerEventsEmitter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TrackCapturerEventsEmitter.h; path = RCTWebRTC/TrackCapturerEventsEmitter.h; sourceTree = SOURCE_ROOT; }; + D7F0711D2C6DC91F0031F594 /* WebRTCModule+RTCAudioSession.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "WebRTCModule+RTCAudioSession.m"; path = "RCTWebRTC/WebRTCModule+RTCAudioSession.m"; sourceTree = SOURCE_ROOT; }; D7F99C122938F4E0000A2450 /* WebRTCModule+RTCMediaStream.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "WebRTCModule+RTCMediaStream.h"; path = "RCTWebRTC/WebRTCModule+RTCMediaStream.h"; sourceTree = SOURCE_ROOT; }; DEC96576264176C10052DB35 /* DataChannelWrapper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = DataChannelWrapper.m; path = RCTWebRTC/DataChannelWrapper.m; sourceTree = ""; }; DEC96579264176DF0052DB35 /* DataChannelWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DataChannelWrapper.h; path = RCTWebRTC/DataChannelWrapper.h; sourceTree = ""; }; @@ -131,6 +133,7 @@ 4EE3A8AF25B8413200FAA24A /* VideoCaptureController.h */, 0BDDA6DF20C18B6B00B38B45 /* VideoCaptureController.m */, 4EE3A8B525B8414A00FAA24A /* WebRTCModule+Permissions.m */, + D7F0711D2C6DC91F0031F594 /* WebRTCModule+RTCAudioSession.m */, 4EE3A8B825B8415900FAA24A /* WebRTCModule+RTCDataChannel.h */, 4EE3A8B925B8415900FAA24A /* WebRTCModule+RTCDataChannel.m */, D7F99C122938F4E0000A2450 /* WebRTCModule+RTCMediaStream.h */, @@ -262,6 +265,7 @@ 4EC498BC25B8777F00E76218 /* ScreenCapturePickerViewManager.m in Sources */, 4EE3A8B225B8414000FAA24A /* WebRTCModule.m in Sources */, 4EE3A8D225B841DD00FAA24A /* CaptureController.m in Sources */, + D7F0711E2C6DC91F0031F594 /* WebRTCModule+RTCAudioSession.m in Sources */, D74EF94829652169000742E1 /* TrackCapturerEventsEmitter.m in Sources */, 4EE3A8D125B841DD00FAA24A /* SocketConnection.m in Sources */, 4EE3A8BD25B8416500FAA24A /* WebRTCModule+RTCMediaStream.m in Sources */, diff --git a/ios/RCTWebRTC/WebRTCModule+RTCAudioSession.m b/ios/RCTWebRTC/WebRTCModule+RTCAudioSession.m new file mode 100644 index 000000000..cd4fa138c --- /dev/null +++ b/ios/RCTWebRTC/WebRTCModule+RTCAudioSession.m @@ -0,0 +1,20 @@ +#import + +#import +#import + +#import "WebRTCModule.h" + +@implementation WebRTCModule (RTCAudioSession) + +RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(audioSessionDidActivate) { + [[RTCAudioSession sharedInstance] audioSessionDidActivate:[AVAudioSession sharedInstance]]; + return nil; +} + +RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(audioSessionDidDeactivate) { + [[RTCAudioSession sharedInstance] audioSessionDidDeactivate:[AVAudioSession sharedInstance]]; + return nil; +} + +@end diff --git a/ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m b/ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m index ccf35b3e8..08ff5cdaa 100644 --- a/ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m +++ b/ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m @@ -262,8 +262,13 @@ - (RTCVideoTrack *)createScreenCaptureVideoTrack { callback(@[]); #else NSMutableArray *devices = [NSMutableArray array]; + NSMutableArray *deviceTypes = [NSMutableArray array]; + [deviceTypes addObjectsFromArray:@[ AVCaptureDeviceTypeBuiltInWideAngleCamera, AVCaptureDeviceTypeBuiltInUltraWideCamera, AVCaptureDeviceTypeBuiltInTelephotoCamera, AVCaptureDeviceTypeBuiltInDualCamera, AVCaptureDeviceTypeBuiltInDualWideCamera, AVCaptureDeviceTypeBuiltInTripleCamera]]; + if (@available(macos 14.0, ios 17.0, tvos 17.0, *)) { + [deviceTypes addObject:AVCaptureDeviceTypeExternal]; + } AVCaptureDeviceDiscoverySession *videoevicesSession = - [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:@[ AVCaptureDeviceTypeBuiltInWideAngleCamera, AVCaptureDeviceTypeBuiltInUltraWideCamera, AVCaptureDeviceTypeBuiltInTelephotoCamera, AVCaptureDeviceTypeBuiltInDualCamera, AVCaptureDeviceTypeBuiltInDualWideCamera, AVCaptureDeviceTypeBuiltInTripleCamera] + [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:deviceTypes mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionUnspecified]; for (AVCaptureDevice *device in videoevicesSession.devices) { @@ -277,6 +282,7 @@ - (RTCVideoTrack *)createScreenCaptureVideoTrack { if (device.localizedName != nil) { label = device.localizedName; } + [devices addObject:@{ @"facing" : position, @"deviceId" : device.uniqueID, diff --git a/src/RTCAudioSession.ts b/src/RTCAudioSession.ts new file mode 100644 index 000000000..f2996e7ae --- /dev/null +++ b/src/RTCAudioSession.ts @@ -0,0 +1,25 @@ +import { NativeModules, Platform } from 'react-native'; + +const { WebRTCModule } = NativeModules; + +export default class RTCAudioSession { + /** + * To be called when CallKit activates the audio session. + */ + static audioSessionDidActivate() { + // Only valid for iOS + if (Platform.OS === 'ios') { + WebRTCModule.audioSessionDidActivate(); + } + } + + /** + * To be called when CallKit deactivates the audio session. + */ + static audioSessionDidDeactivate() { + // Only valid for iOS + if (Platform.OS === 'ios') { + WebRTCModule.audioSessionDidDeactivate(); + } + } +} diff --git a/src/RTCPeerConnection.ts b/src/RTCPeerConnection.ts index 172ca0018..cc88293d7 100644 --- a/src/RTCPeerConnection.ts +++ b/src/RTCPeerConnection.ts @@ -342,7 +342,7 @@ export default class RTCPeerConnection extends EventTarget c.toJSON()), - headerExtensions: this.headerExtensions.map(he => he.toJSON()), - rtcp: this.rtcp.toJSON() + codecs: this.codecs.map(c => deepClone(c)), + headerExtensions: this.headerExtensions.map(he => deepClone(he)), + rtcp: deepClone(this.rtcp) }; } } diff --git a/src/RTCRtpSendParameters.ts b/src/RTCRtpSendParameters.ts index 7b20f7b99..338c60c4b 100644 --- a/src/RTCRtpSendParameters.ts +++ b/src/RTCRtpSendParameters.ts @@ -1,5 +1,6 @@ import RTCRtpEncodingParameters, { RTCRtpEncodingParametersInit } from './RTCRtpEncodingParameters'; import RTCRtpParameters, { RTCRtpParametersInit } from './RTCRtpParameters'; +import { deepClone } from './RTCUtil'; type DegradationPreferenceType = 'maintain-framerate' | 'maintain-resolution' @@ -31,7 +32,7 @@ export interface RTCRtpSendParametersInit extends RTCRtpParametersInit { export default class RTCRtpSendParameters extends RTCRtpParameters { readonly transactionId: string; - readonly encodings: RTCRtpEncodingParameters[]; + encodings: (RTCRtpEncodingParameters | RTCRtpEncodingParametersInit)[]; degradationPreference: DegradationPreferenceType | null; constructor(init: RTCRtpSendParametersInit) { @@ -47,17 +48,16 @@ export default class RTCRtpSendParameters extends RTCRtpParameters { } } - toJSON(): RTCRtpSendParametersInit { + toJSON() { const obj = super.toJSON(); obj['transactionId'] = this.transactionId; - - obj['encodings'] = this.encodings.map(e => e.toJSON()); + obj['encodings'] = this.encodings.map(e => deepClone(e)); if (this.degradationPreference !== null) { obj['degradationPreference'] = DegradationPreference.toNative(this.degradationPreference); } - return obj as RTCRtpSendParametersInit; + return obj; } } diff --git a/src/index.ts b/src/index.ts index b495f3d4e..e47c0042f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -15,6 +15,7 @@ import MediaStream from './MediaStream'; import MediaStreamTrack from './MediaStreamTrack'; import MediaStreamTrackEvent from './MediaStreamTrackEvent'; import permissions from './Permissions'; +import RTCAudioSession from './RTCAudioSession'; import RTCErrorEvent from './RTCErrorEvent'; import RTCIceCandidate from './RTCIceCandidate'; import RTCPeerConnection from './RTCPeerConnection'; @@ -40,6 +41,7 @@ export { RTCRtpReceiver, RTCRtpSender, RTCErrorEvent, + RTCAudioSession, MediaStream, MediaStreamTrack, mediaDevices, From 0eb4be1f0bbfbad0f6e676dd5fa33615975b253f Mon Sep 17 00:00:00 2001 From: davidliu Date: Tue, 20 Aug 2024 01:57:53 +0900 Subject: [PATCH 026/144] release 125.0.3 c10087e Merge upstream 124.0.4 into master (#16) ( davidliu 2024-08-19 14:45:18 +0900) 1121257 ci: fix ios compile (#14) ( davidliu 2024-08-05 14:30:17 +0900) --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index cfd2664e7..0492bb47e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@livekit/react-native-webrtc", - "version": "125.0.2", + "version": "125.0.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@livekit/react-native-webrtc", - "version": "125.0.2", + "version": "125.0.3", "license": "MIT", "dependencies": { "base64-js": "1.5.1", diff --git a/package.json b/package.json index a0b407cf1..73fa376f5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@livekit/react-native-webrtc", - "version": "125.0.2", + "version": "125.0.3", "repository": { "type": "git", "url": "git+https://github.com/livekit/react-native-webrtc.git" From c571bfcd5af44d0094d50ef5f93e4f8755c48984 Mon Sep 17 00:00:00 2001 From: davidliu Date: Mon, 16 Sep 2024 23:00:48 +0900 Subject: [PATCH 027/144] android: don't use rootProject's minSdkVersion (#17) --- android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/build.gradle b/android/build.gradle index 6bc6fb712..a1f49ba23 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -14,7 +14,7 @@ android { buildToolsVersion safeExtGet('buildToolsVersion', "23.0.1") defaultConfig { - minSdkVersion safeExtGet('minSdkVersion', 24) + minSdkVersion 24 targetSdkVersion safeExtGet('targetSdkVersion', 24) versionCode 1 versionName "1.0" From b3e537b61dd35f7ba3643434bb05d7899e706160 Mon Sep 17 00:00:00 2001 From: davidliu Date: Mon, 16 Sep 2024 23:01:23 +0900 Subject: [PATCH 028/144] release 125.0.4 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0492bb47e..8b5b8b6c5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@livekit/react-native-webrtc", - "version": "125.0.3", + "version": "125.0.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@livekit/react-native-webrtc", - "version": "125.0.3", + "version": "125.0.4", "license": "MIT", "dependencies": { "base64-js": "1.5.1", diff --git a/package.json b/package.json index 73fa376f5..155d7aab3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@livekit/react-native-webrtc", - "version": "125.0.3", + "version": "125.0.4", "repository": { "type": "git", "url": "git+https://github.com/livekit/react-native-webrtc.git" From 11bf531524d9985e99e60f2f6e50fc01d610aef8 Mon Sep 17 00:00:00 2001 From: davidliu Date: Tue, 15 Oct 2024 19:58:13 +0900 Subject: [PATCH 029/144] Fix multi-cam support (#18) --- ios/RCTWebRTC/VideoCaptureController.m | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ios/RCTWebRTC/VideoCaptureController.m b/ios/RCTWebRTC/VideoCaptureController.m index 2f8447004..4307e37f3 100644 --- a/ios/RCTWebRTC/VideoCaptureController.m +++ b/ios/RCTWebRTC/VideoCaptureController.m @@ -206,6 +206,13 @@ - (AVCaptureDeviceFormat *)selectFormatForDevice:(AVCaptureDevice *)device int currentDiff = INT_MAX; for (AVCaptureDeviceFormat *format in formats) { + // Only use multi cam formats when on multi cam supported devices. + if (@available(iOS 13.0, macOS 14.0, tvOS 17.0, *)) { + if (AVCaptureMultiCamSession.multiCamSupported && !format.multiCamSupported) { + continue; + } + } + CMVideoDimensions dimension = CMVideoFormatDescriptionGetDimensions(format.formatDescription); FourCharCode pixelFormat = CMFormatDescriptionGetMediaSubType(format.formatDescription); int diff = abs(targetWidth - dimension.width) + abs(targetHeight - dimension.height); @@ -252,4 +259,4 @@ - (void)resetFrameRateForDevice:(AVCaptureDevice *)device { @end -#endif \ No newline at end of file +#endif From 4f58cb2b96f770dc646138b6440f8014c4cc08c3 Mon Sep 17 00:00:00 2001 From: davidliu Date: Tue, 15 Oct 2024 23:05:25 +0900 Subject: [PATCH 030/144] ios: update webrtc-sdk pod to 125.6422.05 (#19) --- livekit-react-native-webrtc.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/livekit-react-native-webrtc.podspec b/livekit-react-native-webrtc.podspec index 6994432d1..6a584ae2d 100644 --- a/livekit-react-native-webrtc.podspec +++ b/livekit-react-native-webrtc.podspec @@ -19,5 +19,5 @@ Pod::Spec.new do |s| s.libraries = 'c', 'sqlite3', 'stdc++' s.framework = 'AudioToolbox','AVFoundation', 'CoreAudio', 'CoreGraphics', 'CoreVideo', 'GLKit', 'VideoToolbox' s.dependency 'React-Core' - s.dependency 'WebRTC-SDK', '~>125.6422.04' + s.dependency 'WebRTC-SDK', '~>125.6422.05' end From a8e2c3b0695fdec6fed5713573426b9f0287a860 Mon Sep 17 00:00:00 2001 From: davidliu Date: Tue, 15 Oct 2024 23:06:01 +0900 Subject: [PATCH 031/144] release 125.0.5 4f58cb2 ios: update webrtc-sdk pod to 125.6422.05 (#19) ( davidliu 2024-10-15 23:05:25 +0900) 11bf531 Fix multi-cam support (#18) ( davidliu 2024-10-15 19:58:13 +0900) --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8b5b8b6c5..89c99ac7c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@livekit/react-native-webrtc", - "version": "125.0.4", + "version": "125.0.5", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@livekit/react-native-webrtc", - "version": "125.0.4", + "version": "125.0.5", "license": "MIT", "dependencies": { "base64-js": "1.5.1", diff --git a/package.json b/package.json index 155d7aab3..957907664 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@livekit/react-native-webrtc", - "version": "125.0.4", + "version": "125.0.5", "repository": { "type": "git", "url": "git+https://github.com/livekit/react-native-webrtc.git" From 4f337cde418a0ea4c79b577810639ffa950c07a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Mon, 4 Nov 2024 13:07:11 +0100 Subject: [PATCH 032/144] doc: remove duplicate / confusing information about screen-sharing (#1645) --- Documentation/AndroidInstallation.md | 72 ---------------------------- 1 file changed, 72 deletions(-) diff --git a/Documentation/AndroidInstallation.md b/Documentation/AndroidInstallation.md index da50cccba..0b00c5b90 100644 --- a/Documentation/AndroidInstallation.md +++ b/Documentation/AndroidInstallation.md @@ -72,78 +72,6 @@ In `android/app/proguard-rules.pro` add the following on a new line. -keep class org.webrtc.** { *; } ``` -## Screen Capture Support - Android 10+ - -You'll need [Notifee](https://notifee.app/react-native/docs/overview) or another library that can handle foreground services for you. -The basic requirement to get screen capturing working since Android 10 and above is to have a foreground service with `mediaProjection` included as a service type and to have that service running before starting a screen capture session. - -In `android/app/main/AndroidManifest.xml` add the following inside the `` section. - -```xml - -``` - -Additionally, add the respective foreground service type permissions before the `` section. - -```xml - - - -``` - -The following will create an ongoing persistent notification which also comes with a foreground service. -You will be prompted for permissions automatically each time you want to initialise screen capturing. -A notification channel is also required and created. - -```javascript -import notifee, { AndroidImportance } from '@notifee/react-native'; - -try { - const channelId = await notifee.createChannel( { - id: 'screen_capture', - name: 'Screen Capture', - lights: false, - vibration: false, - importance: AndroidImportance.DEFAULT - } ); - - await notifee.displayNotification( { - title: 'Screen Capture', - body: 'This notification will be here until you stop capturing.', - android: { - channelId, - asForegroundService: true - } - } ); -} catch( err ) { - // Handle Error -}; -``` - -Once screen capturing has finished you should then stop the foreground service. -Usually you'd run a notification cancellation function but as the service is involved, instead run the following. - -```javascript -try { - await notifee.stopForegroundService(); -} catch( err ) { - // Handle Error -}; -``` - -Lastly, you'll need to add this to your project's main `index.js` file. -Otherwise, you'll receive errors relating to the foreground service not being registered correctly. - -```javascript -notifee.registerForegroundService( notification => { - return new Promise( () => { - - } ); -} ); -``` - ## Fatal Exception: java.lang.UnsatisfiedLinkError ``` From b62727aeab1e879636322be063de396177e41436 Mon Sep 17 00:00:00 2001 From: davidliu Date: Mon, 2 Dec 2024 04:44:14 -0800 Subject: [PATCH 033/144] ios: add background camera access option --- Documentation/iOSInstallation.md | 15 +++++++++++++++ ios/RCTWebRTC/VideoCaptureController.h | 1 + ios/RCTWebRTC/VideoCaptureController.m | 13 +++++++++++++ ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m | 2 ++ ios/RCTWebRTC/WebRTCModuleOptions.h | 1 + 5 files changed, 32 insertions(+) diff --git a/Documentation/iOSInstallation.md b/Documentation/iOSInstallation.md index 783b6570e..2225d5980 100644 --- a/Documentation/iOSInstallation.md +++ b/Documentation/iOSInstallation.md @@ -53,6 +53,21 @@ RTCAudioSession.audioSessionDidActivate(); RTCAudioSession.audioSessionDidDeactivate(); ``` +## Background Camera Access + +Background camera access on supported devices can be enabled through setting the `enableMultitaskingCameraAccess` flag on WebRTCModuleOptions. This will require +the `voip` background mode capability on iOS 18 or later devices. + +In your AppDelegate.m file: +``` +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + [WebRTCModuleOptions sharedInstance].enableMultitaskingCameraAccess = YES; + + // ... +} +``` + ## Library not loaded/Code signature invalid This is an issue with iOS 13.3.1. diff --git a/ios/RCTWebRTC/VideoCaptureController.h b/ios/RCTWebRTC/VideoCaptureController.h index 48a3e538e..d7f2a68f9 100644 --- a/ios/RCTWebRTC/VideoCaptureController.h +++ b/ios/RCTWebRTC/VideoCaptureController.h @@ -8,6 +8,7 @@ @interface VideoCaptureController : CaptureController @property(nonatomic, readonly, strong) AVCaptureDeviceFormat *selectedFormat; @property(nonatomic, readonly, assign) int frameRate; +@property(nonatomic, assign) BOOL enableMultitaskingCameraAccess; - (instancetype)initWithCapturer:(RTCCameraVideoCapturer *)capturer andConstraints:(NSDictionary *)constraints; - (void)startCapture; diff --git a/ios/RCTWebRTC/VideoCaptureController.m b/ios/RCTWebRTC/VideoCaptureController.m index 8c5efff70..0c002cf6c 100644 --- a/ios/RCTWebRTC/VideoCaptureController.m +++ b/ios/RCTWebRTC/VideoCaptureController.m @@ -62,6 +62,19 @@ - (void)startCapture { self.selectedFormat = format; + AVCaptureSession *session = self.capturer.captureSession; + if (@available(iOS 16.0, *)) { + BOOL enable = self.enableMultitaskingCameraAccess; + BOOL shouldChange = session.multitaskingCameraAccessEnabled != enable; + BOOL canChange = !enable || (enable && session.isMultitaskingCameraAccessSupported); + + if(shouldChange && canChange) { + [session beginConfiguration]; + [session setMultitaskingCameraAccessEnabled:enable]; + [session commitConfiguration]; + } + } + RCTLog(@"[VideoCaptureController] Capture will start"); // Starting the capture happens on another thread. Wait for it. diff --git a/ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m b/ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m index 1dc965845..7a12c7c4f 100644 --- a/ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m +++ b/ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m @@ -6,6 +6,7 @@ #import #import "RTCMediaStreamTrack+React.h" +#import "WebRTCModuleOptions.h" #import "WebRTCModule+RTCMediaStream.h" #import "WebRTCModule+RTCPeerConnection.h" @@ -118,6 +119,7 @@ - (RTCVideoTrack *)createVideoTrack:(NSDictionary *)constraints { RTCCameraVideoCapturer *videoCapturer = [[RTCCameraVideoCapturer alloc] initWithDelegate:videoSource]; VideoCaptureController *videoCaptureController = [[VideoCaptureController alloc] initWithCapturer:videoCapturer andConstraints:constraints[@"video"]]; + videoCaptureController.enableMultitaskingCameraAccess = [WebRTCModuleOptions sharedInstance].enableMultitaskingCameraAccess; videoTrack.captureController = videoCaptureController; [videoCaptureController startCapture]; #endif diff --git a/ios/RCTWebRTC/WebRTCModuleOptions.h b/ios/RCTWebRTC/WebRTCModuleOptions.h index 7c91b36e8..d821ec9bf 100644 --- a/ios/RCTWebRTC/WebRTCModuleOptions.h +++ b/ios/RCTWebRTC/WebRTCModuleOptions.h @@ -10,6 +10,7 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, strong, nullable) id audioDevice; @property(nonatomic, strong, nullable) NSDictionary *fieldTrials; @property(nonatomic, assign) RTCLoggingSeverity loggingSeverity; +@property(nonatomic, assign) BOOL enableMultitaskingCameraAccess; #pragma mark - This class is a singleton From 996c128cffdb78628c5b37aceafbcbf496d435c1 Mon Sep 17 00:00:00 2001 From: davidliu Date: Fri, 13 Dec 2024 21:59:33 +0900 Subject: [PATCH 034/144] ios: picture in picture implementation --- examples/GumTestApp/App.js | 32 ++- examples/GumTestApp/ios/GumTestApp/Info.plist | 12 +- ios/RCTWebRTC/I420Converter.h | 21 ++ ios/RCTWebRTC/I420Converter.m | 156 +++++++++++ ios/RCTWebRTC/PIPController.h | 24 ++ ios/RCTWebRTC/PIPController.m | 242 ++++++++++++++++++ ios/RCTWebRTC/RTCVideoViewManager.h | 23 ++ ios/RCTWebRTC/RTCVideoViewManager.m | 128 +++++++-- ios/RCTWebRTC/SampleBufferVideoCallView.h | 12 + ios/RCTWebRTC/SampleBufferVideoCallView.m | 180 +++++++++++++ src/.eslintrc.cjs | 2 +- src/RTCPIPView.tsx | 46 ++++ src/RTCView.ts | 52 +++- src/index.ts | 10 +- tsconfig.json | 4 +- 15 files changed, 907 insertions(+), 37 deletions(-) create mode 100644 ios/RCTWebRTC/I420Converter.h create mode 100644 ios/RCTWebRTC/I420Converter.m create mode 100644 ios/RCTWebRTC/PIPController.h create mode 100644 ios/RCTWebRTC/PIPController.m create mode 100644 ios/RCTWebRTC/SampleBufferVideoCallView.h create mode 100644 ios/RCTWebRTC/SampleBufferVideoCallView.m create mode 100644 src/RTCPIPView.tsx diff --git a/examples/GumTestApp/App.js b/examples/GumTestApp/App.js index e9e9fe6c3..03dc47922 100644 --- a/examples/GumTestApp/App.js +++ b/examples/GumTestApp/App.js @@ -6,7 +6,7 @@ * @flow strict-local */ -import React, {useState} from 'react'; +import React, {useState, useRef} from 'react'; import { Button, SafeAreaView, @@ -15,10 +15,11 @@ import { StatusBar, } from 'react-native'; import { Colors } from 'react-native/Libraries/NewAppScreen'; -import { mediaDevices, RTCView } from 'react-native-webrtc'; +import { mediaDevices, startIOSPIP, stopIOSPIP, RTCPIPView } from 'react-native-webrtc'; const App = () => { + const view = useRef() const [stream, setStream] = useState(null); const start = async () => { console.log('start'); @@ -31,6 +32,12 @@ const App = () => { } } }; + const startPIP = () => { + startIOSPIP(view); + }; + const stopPIP = () => { + stopIOSPIP(view); + }; const stop = () => { console.log('stop'); if (stream) { @@ -38,21 +45,38 @@ const App = () => { setStream(null); } }; + let pipOptions = { + startAutomatically: true, + fallbackView: (), + preferredSize: { + width: 400, + height: 800, + } + } return ( <> { stream && - + style={styles.stream} + iosPIP={pipOptions} > + }