Skip to content

Commit 0024b29

Browse files
committed
Merge upstream master into LiveKit fork
Syncs with upstream react-native-webrtc while preserving LiveKit-specific changes (crypto APIs, WebRTC-SDK dependency, constraint handling, etc.)
2 parents 1ff4ef3 + e36ddec commit 0024b29

32 files changed

Lines changed: 2021 additions & 378 deletions

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
examples
22
lib
3+
src/vendor
34
tools
45

56
metro.*.js

Documentation/BuildingWebRTC.md

Lines changed: 1 addition & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,2 @@
11
# Building WebRTC
2-
3-
This document shows how to prepare a WebRTC build for its inclusion in this
4-
plugin.
5-
The build will be made with the `build-webrtc.py` Python script located in the
6-
`tools/` directory.
7-
8-
## Preparing the build
9-
10-
Running the script with `--setup` will download all necessary tools for building
11-
WebRTC. The script must be run with a target directory where all WebRTC source
12-
code and resulting build artifacts will be placed. A `build_webrtc` directory
13-
will be created containing it all.
14-
The setup process only needs to be carried out once.
15-
16-
### iOS
17-
18-
```
19-
python build-webrtc.py --setup --ios ~/src/
20-
```
21-
22-
### Android
23-
24-
NOTE: Make sure you have the Java JDK installed beforehand. On Debian and
25-
Ubuntu systems, this can be accomplished by installing the `default-jdk-headless`
26-
package.
27-
28-
```
29-
python build-webrtc.py --setup --android ~/src/
30-
```
31-
32-
### Selecting the branch
33-
34-
Once the setup process has finished, the target branch must be selected, also
35-
adding any required cherry-picks. The following example shows how the M87 branch
36-
was made:
37-
38-
```
39-
cd ~/src/build_webrtc/webrtc/ios/src/
40-
git checkout -b build-M87 refs/remotes/branch-heads/4280
41-
#git cherry-pick ...
42-
cd
43-
```
44-
45-
Now the code is ready for building!
46-
Notice that since M79 chromium changed the branch naming scheme, for example M87 is WebRTC branch 4280.
47-
For a full list of branches, see: https://chromiumdash.appspot.com/branches
48-
49-
## Building
50-
51-
### iOS
52-
53-
If you have switched branches, first run:
54-
55-
```
56-
python build-webrtc.py --sync --ios ~/src/
57-
```
58-
59-
Now build it:
60-
61-
```
62-
python build-webrtc.py --build --ios ~/src/
63-
```
64-
65-
The build artifacts will be located in `~/src/build_webrtc/build/ios/`.
66-
67-
### Android
68-
69-
**NOTE**: WebRTC for Android can only be built on Linux.
70-
If you have switched branches, first run:
71-
72-
```
73-
python build-webrtc.py --sync --android ~/src/
74-
```
75-
76-
Now build it:
77-
78-
```
79-
python build-webrtc.py --build --android ~/src/
80-
```
81-
82-
The build artifacts will be located in `~/src/build_webrtc/build/android/`.
83-
84-
### Making debug builds
85-
86-
Debug builds can be made by adding `--debug` together with `--build`. For example, to make a debug iOS build:
87-
88-
```
89-
python build-webrtc.py --build --ios --debug ~/src/
90-
```
2+
The scripts and documentation for the custom build are now located in [jitsi/webrtc](https://github.com/jitsi/webrtc). See the README in that repository for further instructions.

android/src/main/java/com/oney/WebRTCModule/SerializeUtils.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,9 @@ public static ReadableMap serializeRtpParameters(RtpParameters params) {
150150
if (encoding.maxBitrateBps != null) {
151151
encodingMap.putInt("maxBitrate", encoding.maxBitrateBps);
152152
}
153+
if (encoding.minBitrateBps != null) {
154+
encodingMap.putInt("minBitrate", encoding.minBitrateBps);
155+
}
153156
if (encoding.maxFramerate != null) {
154157
encodingMap.putInt("maxFramerate", encoding.maxFramerate);
155158
}
@@ -238,6 +241,7 @@ public static RtpParameters updateRtpParameters(ReadableMap updateParams, RtpPar
238241
RtpParameters.Encoding encoding = encodings.get(i);
239242
// Dealing with nullable Integers
240243
Integer maxBitrate = encodingUpdate.hasKey("maxBitrate") ? encodingUpdate.getInt("maxBitrate") : null;
244+
Integer minBitrate = encodingUpdate.hasKey("minBitrate") ? encodingUpdate.getInt("minBitrate") : null;
241245
Integer maxFramerate = encodingUpdate.hasKey("maxFramerate") ? encodingUpdate.getInt("maxFramerate") : null;
242246
Double scaleResolutionDownBy = encodingUpdate.hasKey("scaleResolutionDownBy")
243247
? encodingUpdate.getDouble("scaleResolutionDownBy")
@@ -246,6 +250,7 @@ public static RtpParameters updateRtpParameters(ReadableMap updateParams, RtpPar
246250
encoding.active = encodingUpdate.getBoolean("active");
247251
encoding.rid = encodingUpdate.getString("rid");
248252
encoding.maxBitrateBps = maxBitrate;
253+
encoding.minBitrateBps = minBitrate;
249254
encoding.maxFramerate = maxFramerate;
250255
encoding.scaleResolutionDownBy = scaleResolutionDownBy;
251256
}
@@ -294,6 +299,9 @@ private static RtpParameters.Encoding parseEncoding(ReadableMap params) {
294299
if (params.hasKey("maxBitrate")) {
295300
encoding.maxBitrateBps = params.getInt("maxBitrate");
296301
}
302+
if (params.hasKey("minBitrate")) {
303+
encoding.minBitrateBps = params.getInt("minBitrate");
304+
}
297305
if (params.hasKey("maxFramerate")) {
298306
encoding.maxFramerate = params.getInt("maxFramerate");
299307
}

android/src/main/java/com/oney/WebRTCModule/WebRTCModule.java

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,10 @@ public WebRTCModule(ReactApplicationContext reactContext) {
9191
String fieldTrials = options.fieldTrials;
9292

9393
PeerConnectionFactory.initialize(PeerConnectionFactory.InitializationOptions.builder(reactContext)
94-
.setFieldTrials(fieldTrials)
95-
.setNativeLibraryLoader(new LibraryLoader())
96-
.setInjectableLogger(injectableLogger, loggingSeverity)
97-
.createInitializationOptions());
94+
.setFieldTrials(fieldTrials)
95+
.setNativeLibraryLoader(new LibraryLoader())
96+
.setInjectableLogger(injectableLogger, loggingSeverity)
97+
.createInitializationOptions());
9898

9999
if (injectableLogger == null && loggingSeverity != null) {
100100
Logging.enableLogToDebugOutput(loggingSeverity);
@@ -436,33 +436,23 @@ public boolean peerConnectionInit(ReadableMap configuration, int id) {
436436
}
437437
}
438438

439+
// Must be called in the executor.
439440
MediaStream getStreamForReactTag(String streamReactTag) {
440-
// This function _only_ gets called from WebRTCView, in the UI thread.
441-
// Hence make sure we run this code in the executor or we run at the risk
442-
// of being out of sync.
443-
try {
444-
return (MediaStream) ThreadUtils
445-
.submitToExecutor((Callable<Object>) () -> {
446-
MediaStream stream = localStreams.get(streamReactTag);
447-
448-
if (stream != null) {
449-
return stream;
450-
}
441+
MediaStream stream = localStreams.get(streamReactTag);
451442

452-
for (int i = 0, size = mPeerConnectionObservers.size(); i < size; i++) {
453-
PeerConnectionObserver pco = mPeerConnectionObservers.valueAt(i);
454-
stream = pco.remoteStreams.get(streamReactTag);
455-
if (stream != null) {
456-
return stream;
457-
}
458-
}
443+
if (stream != null) {
444+
return stream;
445+
}
459446

460-
return null;
461-
})
462-
.get();
463-
} catch (ExecutionException | InterruptedException e) {
464-
return null;
447+
for (int i = 0, size = mPeerConnectionObservers.size(); i < size; i++) {
448+
PeerConnectionObserver pco = mPeerConnectionObservers.valueAt(i);
449+
stream = pco.remoteStreams.get(streamReactTag);
450+
if (stream != null) {
451+
return stream;
452+
}
465453
}
454+
455+
return null;
466456
}
467457

468458
public MediaStreamTrack getTrack(int pcId, String trackId) {

android/src/main/java/com/oney/WebRTCModule/WebRTCView.java

Lines changed: 56 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -173,28 +173,53 @@ private void cleanSurfaceViewRenderer() {
173173
surfaceViewRenderer.clearImage();
174174
}
175175

176-
private VideoTrack getVideoTrackForStreamURL(String streamURL) {
177-
VideoTrack videoTrack = null;
176+
/**
177+
* Asynchronously retrieves the VideoTrack for the given streamURL.
178+
* This method avoids blocking the UI thread by performing the lookup
179+
* on the WebRTC executor thread and posting the result back to the UI thread.
180+
*
181+
* @param streamURL The stream URL to lookup
182+
* @param callback Callback invoked on UI thread with the VideoTrack (or null if not found)
183+
*/
184+
private void getVideoTrackForStreamURL(String streamURL, java.util.function.Consumer<VideoTrack> callback) {
185+
if (streamURL == null) {
186+
callback.accept(null);
187+
return;
188+
}
178189

179-
if (streamURL != null) {
180-
ReactContext reactContext = (ReactContext) getContext();
181-
WebRTCModule module = reactContext.getNativeModule(WebRTCModule.class);
182-
MediaStream stream = module.getStreamForReactTag(streamURL);
190+
ReactContext reactContext = (ReactContext) getContext();
191+
WebRTCModule module = reactContext.getNativeModule(WebRTCModule.class);
183192

184-
if (stream != null) {
185-
List<VideoTrack> videoTracks = stream.videoTracks;
193+
// Submit lookup to executor thread to avoid blocking UI thread
194+
ThreadUtils.runOnExecutor(() -> {
195+
try {
196+
MediaStream stream = module.getStreamForReactTag(streamURL);
197+
if (stream == null) {
198+
Log.w(TAG, "Stream not found for URL: " + streamURL);
199+
post(() -> callback.accept(null));
200+
return;
201+
}
186202

203+
VideoTrack videoTrack = null;
204+
List<VideoTrack> videoTracks = stream.videoTracks;
187205
if (!videoTracks.isEmpty()) {
188206
videoTrack = videoTracks.get(0);
189207
}
190-
}
191208

192-
if (videoTrack == null) {
193-
Log.w(TAG, "No video stream for react tag: " + streamURL);
194-
}
195-
}
209+
if (videoTrack == null) {
210+
Log.w(TAG, "No video stream for react tag: " + streamURL);
211+
post(() -> callback.accept(null));
212+
return;
213+
}
196214

197-
return videoTrack;
215+
// Post result back to UI thread
216+
final VideoTrack result = videoTrack;
217+
post(() -> callback.accept(result));
218+
} catch (Throwable tr) {
219+
Log.e(TAG, "Error getting video track for stream URL: " + streamURL, tr);
220+
post(() -> callback.accept(null));
221+
}
222+
});
198223
}
199224

200225
@Override
@@ -452,20 +477,23 @@ private void setScalingType(ScalingType scalingType) {
452477
* this {@code WebRTCView} or {@code null}.
453478
*/
454479
void setStreamURL(String streamURL) {
455-
// Is the value of this.streamURL really changing?
456-
if (!Objects.equals(streamURL, this.streamURL)) {
457-
// XXX The value of this.streamURL is really changing. Before
458-
// realizing/applying the change, let go of the old videoTrack. Of
459-
// course, that is only necessary if the value of videoTrack will
460-
// really change. Please note though that letting go of the old
461-
// videoTrack before assigning to this.streamURL is vital;
462-
// otherwise, removeRendererFromVideoTrack will fail to remove the
463-
// old videoTrack from the associated videoRenderer, two
464-
// VideoTracks (the old and the new) may start rendering and, most
465-
// importantly the videoRender may eventually crash when the old
466-
// videoTrack is disposed.
467-
VideoTrack videoTrack = getVideoTrackForStreamURL(streamURL);
480+
Log.d(TAG, "Set stream URL " + streamURL + " current: " + this.streamURL);
481+
if (Objects.equals(streamURL, this.streamURL)) {
482+
return;
483+
}
468484

485+
// The value of this.streamURL is really changing. Before
486+
// realizing/applying the change, let go of the old videoTrack. Of
487+
// course, that is only necessary if the value of videoTrack will
488+
// really change. Please note though that letting go of the old
489+
// videoTrack before assigning to this.streamURL is vital;
490+
// otherwise, removeRendererFromVideoTrack will fail to remove the
491+
// old videoTrack from the associated videoRenderer, two
492+
// VideoTracks (the old and the new) may start rendering and, most
493+
// importantly the videoRender may eventually crash when the old
494+
// videoTrack is disposed.
495+
getVideoTrackForStreamURL(streamURL, videoTrack -> {
496+
Log.d(TAG, "Got video track for stream URL " + streamURL + " -> " + videoTrack);
469497
if (this.videoTrack != videoTrack) {
470498
setVideoTrack(null);
471499
}
@@ -475,7 +503,7 @@ void setStreamURL(String streamURL) {
475503
// After realizing/applying the change in the value of
476504
// this.streamURL, reflect it on the value of videoTrack.
477505
setVideoTrack(videoTrack);
478-
}
506+
});
479507
}
480508

481509
/**

ios/RCTWebRTC/SerializeUtils.m

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ + (NSDictionary *)parametersToJSON:(RTCRtpParameters *)params {
106106
if (encoding.maxBitrateBps) {
107107
encodingDictionary[@"maxBitrate"] = encoding.maxBitrateBps;
108108
}
109+
if (encoding.minBitrateBps) {
110+
encodingDictionary[@"minBitrate"] = encoding.minBitrateBps;
111+
}
109112
if (encoding.maxFramerate) {
110113
encodingDictionary[@"maxFramerate"] = encoding.maxFramerate;
111114
}
@@ -254,6 +257,9 @@ + (RTCRtpEncodingParameters *)parseEncoding:(NSDictionary *)params {
254257
if (params[@"maxBitrate"] != nil) {
255258
[encoding setMaxBitrateBps:(NSNumber *)params[@"maxBitrate"]];
256259
}
260+
if (params[@"minBitrate"] != nil) {
261+
[encoding setMinBitrateBps:(NSNumber *)params[@"minBitrate"]];
262+
}
257263
if (params[@"maxFramerate"] != nil) {
258264
[encoding setMaxFramerate:(NSNumber *)params[@"maxFramerate"]];
259265
}

ios/RCTWebRTC/VideoCaptureController.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ - (void)applyConstraints:(NSDictionary *)constraints error:(NSError **)outError
186186
}
187187
}
188188

189+
189190
- (NSDictionary *)getSettings {
190191
AVCaptureDeviceFormat *format = self.selectedFormat;
191192
CMVideoDimensions dimensions = CMVideoFormatDescriptionGetDimensions(format.formatDescription);

ios/RCTWebRTC/WebRTCModule+Permissions.m

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,8 @@ - (AVMediaType)avMediaType:(NSString *)mediaType {
1919
}
2020
}
2121

22-
RCT_EXPORT_METHOD(checkPermission
23-
: (NSString *)mediaType resolver
24-
: (RCTPromiseResolveBlock)resolve rejecter
25-
: (RCTPromiseRejectBlock)reject) {
22+
RCT_EXPORT_METHOD(checkPermission : (NSString *)mediaType resolver : (RCTPromiseResolveBlock)
23+
resolve rejecter : (RCTPromiseRejectBlock)reject) {
2624
#if TARGET_OS_TV
2725
resolve(@"tvOS is not supported");
2826
return;
@@ -50,10 +48,8 @@ - (AVMediaType)avMediaType:(NSString *)mediaType {
5048
#endif
5149
}
5250

53-
RCT_EXPORT_METHOD(requestPermission
54-
: (NSString *)mediaType resolver
55-
: (RCTPromiseResolveBlock)resolve rejecter
56-
: (RCTPromiseRejectBlock)reject) {
51+
RCT_EXPORT_METHOD(requestPermission : (NSString *)mediaType resolver : (RCTPromiseResolveBlock)
52+
resolve rejecter : (RCTPromiseRejectBlock)reject) {
5753
#if TARGET_OS_TV
5854
resolve(@"tvOS is not supported");
5955
return;

0 commit comments

Comments
 (0)