Skip to content

Commit f3cb1a0

Browse files
committed
Merge remote-tracking branch 'upstream/master' into dl/upstream_merge_july2025
2 parents 132c859 + f515ee5 commit f3cb1a0

29 files changed

+484
-718
lines changed

.github/workflows/android_ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@ jobs:
1313
android-compile:
1414
runs-on: ubuntu-latest
1515
steps:
16-
- uses: actions/checkout@v3
16+
- uses: actions/checkout@v4
1717
- uses: actions/setup-java@v4
1818
with:
1919
distribution: 'temurin'
2020
java-version: '17'
21-
- uses: actions/setup-node@v3
21+
- uses: actions/setup-node@v4
2222
with:
23-
node-version: '16.x'
23+
node-version-file: '.nvmrc'
2424
cache: 'npm'
2525
cache-dependency-path: '**/package-lock.json'
2626

.github/workflows/ci.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ jobs:
77
name: Lint
88
runs-on: ubuntu-latest
99
steps:
10-
- uses: actions/checkout@v3
11-
- uses: actions/setup-node@v3
10+
- uses: actions/checkout@v4
11+
- uses: actions/setup-node@v4
1212
with:
13-
node-version: 16
13+
node-version-file: '.nvmrc'
14+
cache: 'npm'
1415
- run: npm install
1516
- name: Check if the git repository is clean
1617
run: $(exit $(git status --porcelain --untracked-files=no | head -255 | wc -l)) || (echo "Dirty git tree"; git diff; exit 1)

.github/workflows/ios_ci.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,10 @@ jobs:
1313
ios-compile:
1414
runs-on: macos-latest
1515
steps:
16-
- uses: actions/checkout@v3
17-
18-
- uses: actions/setup-node@v3
16+
- uses: actions/checkout@v4
17+
- uses: actions/setup-node@v4
1918
with:
20-
node-version: '16.x'
19+
node-version-file: '.nvmrc'
2120
cache: 'npm'
2221
cache-dependency-path: '**/package-lock.json'
2322

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
22

Documentation/AndroidInstallation.md

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,53 @@ compileOptions {
6464
}
6565
```
6666

67-
## R8/ProGuard Support
67+
## Set audio category (output) to media
6868

69-
In `android/app/proguard-rules.pro` add the following on a new line.
69+
The audio is considered calls by default. If you don't want your audio to be treated as a call stream you need to change the category. To set the category:
7070

71-
```proguard
72-
-keep class org.webrtc.** { *; }
71+
if your Android files are written in Java, modify `MainApplication.java`:
72+
```java
73+
// add imports
74+
import com.oney.WebRTCModule.WebRTCModuleOptions;
75+
import android.media.AudioAttributes;
76+
import org.webrtc.audio.JavaAudioDeviceModule;
77+
78+
public class MainApplication extends Application implements ReactApplication {
79+
@Override
80+
public void onCreate() {
81+
// append this before WebRTCModule initializes
82+
WebRTCModuleOptions options = WebRTCModuleOptions.getInstance();
83+
AudioAttributes audioAttributes = AudioAttributes.Builder()
84+
.setUsage(AudioAttributes.USAGE_MEDIA)
85+
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
86+
.build();
87+
options.audioDeviceModule = JavaAudioDeviceModule.builder(this)
88+
.setAudioAttributes(audioAttributes)
89+
.createAudioDeviceModule();
90+
}
91+
}
92+
```
93+
94+
if your Android files are written in Kotlin, modify `MainApplication.kt`:
95+
```kt
96+
// add imports
97+
import com.oney.WebRTCModule.WebRTCModuleOptions;
98+
import android.media.AudioAttributes
99+
import org.webrtc.audio.JavaAudioDeviceModule;
100+
101+
class MainApplication : Application(), ReactApplication {
102+
override fun onCreate() {
103+
// append this before WebRTCModule initializes
104+
val options = WebRTCModuleOptions.getInstance()
105+
val audioAttributes = AudioAttributes.Builder()
106+
.setUsage(AudioAttributes.USAGE_MEDIA)
107+
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
108+
.build()
109+
options.audioDeviceModule = JavaAudioDeviceModule.builder(this)
110+
.setAudioAttributes(audioAttributes)
111+
.createAudioDeviceModule()
112+
}
113+
}
73114
```
74115

75116
## Fatal Exception: java.lang.UnsatisfiedLinkError

android/build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ android {
1818
targetSdkVersion safeExtGet('targetSdkVersion', 24)
1919
versionCode 1
2020
versionName "1.0"
21+
consumerProguardFiles 'consumer-rules.pro'
2122
}
2223

2324
// WebRTC requires Java 8 features
@@ -29,7 +30,7 @@ android {
2930
}
3031

3132
dependencies {
32-
implementation 'com.facebook.react:react-native:+'
33+
implementation "com.facebook.react:react-android:+"
3334
api 'io.github.webrtc-sdk:android:125.6422.04'
3435
implementation "androidx.core:core:1.7.0"
3536
}

android/consumer-rules.pro

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# WebRTC
2+
-keep class org.webrtc.** { *; }

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
import android.content.Context;
44
import android.hardware.camera2.CameraManager;
55
import android.util.Log;
6+
import android.util.Pair;
7+
8+
import androidx.annotation.Nullable;
9+
import androidx.core.util.Consumer;
610

711
import androidx.annotation.Nullable;
812
import androidx.core.util.Consumer;
@@ -239,8 +243,8 @@ private void updateActualSize(int cameraIndex, String cameraName, VideoCapturer
239243
* {@code null} and a {@code VideoCapturer} can be created for it, then
240244
* {@code facingMode} is ignored.
241245
* @param facingMode the facing of the requested video source such as
242-
* {@code user} and {@code environment}. If {@code null}, "user" is
243-
* presumed.
246+
* {@code user} and {@code environment}. If {@code null}, "user" is
247+
* presumed.
244248
* @return a pair containing the deviceId and {@code VideoCapturer} satisfying the {@code facingMode} or
245249
* {@code deviceId} constraint, or null.
246250
*/

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

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@
2727

2828
import java.util.ArrayList;
2929
import java.util.HashMap;
30+
import java.util.List;
3031
import java.util.Map;
32+
import java.util.Objects;
3133
import java.util.UUID;
34+
import java.util.stream.Collectors;
3235

3336
/**
3437
* The implementation of {@code getUserMedia} extracted into a separate file in
@@ -405,28 +408,35 @@ VideoTrack createVideoTrack(AbstractVideoCaptureController videoCaptureControlle
405408
}
406409

407410
/**
408-
* Set video effect to the TrackPrivate corresponding to the trackId with the help of VideoEffectProcessor
409-
* corresponding to the name.
411+
* Set video effects to the TrackPrivate corresponding to the trackId with the help of VideoEffectProcessor
412+
* corresponding to the names.
410413
* @param trackId TrackPrivate id
411-
* @param name VideoEffectProcessor name
414+
* @param names VideoEffectProcessor names
412415
*/
413-
void setVideoEffect(String trackId, String name) {
416+
void setVideoEffects(String trackId, ReadableArray names) {
414417
TrackPrivate track = tracks.get(trackId);
415418

416419
if (track != null && track.videoCaptureController instanceof CameraCaptureController) {
417420
VideoSource videoSource = (VideoSource) track.mediaSource;
418421
SurfaceTextureHelper surfaceTextureHelper = track.surfaceTextureHelper;
419422

420-
if (name != null) {
421-
VideoFrameProcessor videoFrameProcessor = ProcessorProvider.getProcessor(name);
422-
423-
if (videoFrameProcessor == null) {
424-
Log.e(TAG, "no videoFrameProcessor associated with this name");
425-
return;
426-
}
427-
428-
VideoEffectProcessor videoEffectProcessor =
429-
new VideoEffectProcessor(videoFrameProcessor, surfaceTextureHelper);
423+
if (names != null) {
424+
List<VideoFrameProcessor> processors =
425+
names.toArrayList()
426+
.stream()
427+
.filter(name -> name instanceof String)
428+
.map(name -> {
429+
VideoFrameProcessor videoFrameProcessor =
430+
ProcessorProvider.getProcessor((String) name);
431+
if (videoFrameProcessor == null) {
432+
Log.e(TAG, "no videoFrameProcessor associated with this name: " + name);
433+
}
434+
return videoFrameProcessor;
435+
})
436+
.filter(Objects::nonNull)
437+
.collect(Collectors.toList());
438+
439+
VideoEffectProcessor videoEffectProcessor = new VideoEffectProcessor(processors, surfaceTextureHelper);
430440
videoSource.setVideoProcessor(videoEffectProcessor);
431441

432442
} else {

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

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,11 @@ public WebRTCModule(ReactApplicationContext reactContext) {
9090
Logging.Severity loggingSeverity = options.loggingSeverity;
9191
String fieldTrials = options.fieldTrials;
9292

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

10199
if (injectableLogger == null && loggingSeverity != null) {
102100
Logging.enableLogToDebugOutput(loggingSeverity);
@@ -749,7 +747,7 @@ public void transceiverSetDirection(int id, String senderId, String direction, P
749747
}
750748

751749
@ReactMethod(isBlockingSynchronousMethod = true)
752-
public void transceiverSetCodecPreferences(int id, String senderId, ReadableArray codecPreferences) {
750+
public boolean transceiverSetCodecPreferences(int id, String senderId, ReadableArray codecPreferences) {
753751
ThreadUtils.runOnExecutor(() -> {
754752
WritableMap identifier = Arguments.createMap();
755753
WritableMap params = Arguments.createMap();
@@ -808,6 +806,7 @@ public void transceiverSetCodecPreferences(int id, String senderId, ReadableArra
808806
Log.d(TAG, "transceiverSetCodecPreferences(): " + e.getMessage());
809807
}
810808
});
809+
return true;
811810
}
812811

813812
@ReactMethod
@@ -983,8 +982,8 @@ private ReadableArray getTransceiversInfo(PeerConnection peerConnection) {
983982
}
984983

985984
@ReactMethod
986-
public void mediaStreamTrackSetVideoEffect(String id, String name) {
987-
ThreadUtils.runOnExecutor(() -> { getUserMediaImpl.setVideoEffect(id, name); });
985+
public void mediaStreamTrackSetVideoEffects(String id, ReadableArray names) {
986+
ThreadUtils.runOnExecutor(() -> { getUserMediaImpl.setVideoEffects(id, names); });
988987
}
989988

990989
@ReactMethod

0 commit comments

Comments
 (0)