Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
4539f11
perf: deduplicate WebRTC stats polling
Aug 29, 2026
2678517
perf: reduce auxiliary stream polling
Aug 29, 2026
af83ddd
chore: translate optimization comments to English
Aug 29, 2026
e565c11
perf: pause performance polling in background
Aug 29, 2026
0c0ce7d
perf: disable verbose input logs in production
Aug 29, 2026
e906cca
perf: bound processed frame metadata queue
Aug 29, 2026
5b4dd3e
perf: remove redundant orientation timers
Aug 29, 2026
2cfa8f1
perf: avoid typed array allocations in input packets
Aug 29, 2026
e8f65e9
perf: avoid redundant FSR renderer updates
Aug 29, 2026
2e6f832
perf: reduce verbose FSR logging
Aug 29, 2026
c98473e
perf: reuse FSR texture size buffer
Aug 29, 2026
5c20b95
fix: persist FSR fallback after draw failure
Aug 29, 2026
ef128ca
perf: cache fallback drawer reflection methods
Aug 29, 2026
d58153a
perf: reuse FSR output size buffer
Aug 29, 2026
46c1870
perf: cache HDR tone mapping decision
Aug 29, 2026
fa92b42
perf: disable FSR on low-memory devices
Aug 29, 2026
a6bf4a2
fix: release FSR resources on fallback
Aug 29, 2026
73cd299
fix: sequence video renderer cleanup
Aug 29, 2026
f2a97c1
perf: reduce renderer and overlay overhead
Aug 29, 2026
2eaf632
perf: prevent overlapping performance polls
Aug 29, 2026
2335697
perf: skip redundant video layout updates
Aug 29, 2026
43d5182
perf: release WebRTC session state between streams
Aug 29, 2026
546079f
perf: release WebRTC session callbacks
Aug 29, 2026
1674460
perf: release remote media tracks on cleanup
Aug 29, 2026
6a2c966
perf: unmount inactive touch overlay
Aug 29, 2026
8c2b74f
perf: disable mobile features on Android TV
Aug 29, 2026
1f6ab72
perf: release ICE candidates after negotiation
Aug 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 125 additions & 35 deletions android/app/src/main/java/com/oney/WebRTCModule/RTCFsrVideoView.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.oney.WebRTCModule;

import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Point;
Expand Down Expand Up @@ -52,6 +53,12 @@ public class RTCFsrVideoView extends ViewGroup {
private int frameWidth;
private boolean mirror;
private boolean rendererAttached;
private boolean rendererCleanupInProgress;
private boolean hasAppliedLayout;
private int appliedLayoutLeft;
private int appliedLayoutTop;
private int appliedLayoutRight;
private int appliedLayoutBottom;
private ScalingType scalingType;
private int videoFormatMode = VIDEO_FORMAT_MODE_AUTO;
private float videoFormatAspectRatio;
Expand All @@ -61,10 +68,17 @@ public class RTCFsrVideoView extends ViewGroup {
private VideoTrack videoTrack;

private boolean fsrEnabled = true;
private boolean autoDisableFsrOnLowMemory;
private boolean fsrFallbackActive;
private float fsrSharpness = 2f;
private boolean fsrInitialized;
private float appliedFsrSharpness = Float.NaN;
private int appliedSurfaceWidth = -1;
private int appliedSurfaceHeight = -1;
private Object fsrDrawerProxy;
private Object fallbackDrawer;
private Method fallbackDrawOesMethod;
private Method fallbackReleaseMethod;

private final FsrVideoProcessor fsrVideoProcessor;

Expand Down Expand Up @@ -228,34 +242,58 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
}

if (hasAppliedLayout
&& appliedLayoutLeft == l
&& appliedLayoutTop == t
&& appliedLayoutRight == r
&& appliedLayoutBottom == b) {
return;
}
appliedLayoutLeft = l;
appliedLayoutTop = t;
appliedLayoutRight = r;
appliedLayoutBottom = b;
hasAppliedLayout = true;
surfaceViewRenderer.layout(l, t, r, b);
applyRendererLayoutAspectRatio(r - l, b - t);
}

private void removeRendererFromVideoTrack() {
if (rendererAttached) {
if (videoTrack != null) {
ThreadUtils.runOnExecutor(() -> {
try {
videoTrack.removeSink(surfaceViewRenderer);
} catch (Throwable ignored) {
// Ignore track lifecycle race.
if (!rendererAttached || rendererCleanupInProgress) {
return;
}

rendererAttached = false;
rendererCleanupInProgress = true;
VideoTrack track = videoTrack;
ThreadUtils.runOnExecutor(() -> {
try {
if (track != null) {
track.removeSink(surfaceViewRenderer);
}
} catch (Throwable ignored) {
// Ignore track lifecycle race.
} finally {
surfaceViewRenderer.release();
releaseDrawerResources();
if (surfaceViewRendererInstances > 0) {
surfaceViewRendererInstances--;
}
post(() -> {
rendererCleanupInProgress = false;
synchronized (layoutSyncRoot) {
frameHeight = 0;
frameRotation = 0;
frameWidth = 0;
}
hasAppliedLayout = false;
requestSurfaceViewRendererLayout();
if (videoTrack != null && ViewCompat.isAttachedToWindow(this)) {
tryAddRendererToVideoTrack();
}
});
}

surfaceViewRenderer.release();
releaseDrawerResources();
surfaceViewRendererInstances--;
rendererAttached = false;

synchronized (layoutSyncRoot) {
frameHeight = 0;
frameRotation = 0;
frameWidth = 0;
}
requestSurfaceViewRendererLayout();
}
});
}

@SuppressLint("WrongCall")
Expand Down Expand Up @@ -489,16 +527,40 @@ public void setZOrder(int zOrder) {

public void setFsrEnabled(boolean enabled) {
fsrEnabled = enabled;
fsrVideoProcessor.setFsrEnabled(enabled);
if (enabled) {
fsrFallbackActive = false;
}
applyEffectiveFsrEnabled();
}

public void setAutoDisableFsrOnLowMemory(boolean enabled) {
autoDisableFsrOnLowMemory = enabled;
applyEffectiveFsrEnabled();
}

private void applyEffectiveFsrEnabled() {
boolean lowMemoryDevice = false;
if (autoDisableFsrOnLowMemory) {
ActivityManager activityManager =
(ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE);
lowMemoryDevice = activityManager != null && activityManager.isLowRamDevice();
}
boolean effectiveEnabled = fsrEnabled && !lowMemoryDevice;
if (effectiveEnabled) {
fsrFallbackActive = false;
}
fsrVideoProcessor.setFsrEnabled(effectiveEnabled);
}

public void setFsrSharpness(float sharpness) {
fsrSharpness = sharpness;
appliedFsrSharpness = Float.NaN;
fsrVideoProcessor.setSharpness(sharpness / 10f);
}

private void tryAddRendererToVideoTrack() {
if (!rendererAttached && videoTrack != null && ViewCompat.isAttachedToWindow(this)) {
if (!rendererAttached && !rendererCleanupInProgress
&& videoTrack != null && ViewCompat.isAttachedToWindow(this)) {
EglBase.Context sharedContext = EglUtils.getRootEglBaseContext();

if (sharedContext == null) {
Expand Down Expand Up @@ -627,7 +689,7 @@ private void handleDrawOes(Object[] args) {
return;
}

if (!fsrEnabled) {
if (!fsrEnabled || fsrFallbackActive) {
invokeFallbackDrawer("drawOes", args);
return;
}
Expand All @@ -652,11 +714,18 @@ private void handleDrawOes(Object[] args) {
}

ensureFsrInitialized();
fsrVideoProcessor.setSharpness(fsrSharpness / 10f);
if (viewportWidth > 0 && viewportHeight > 0) {
fsrVideoProcessor.setSurfaceSize(viewportWidth, viewportHeight);
} else if (frameWidth > 0 && frameHeight > 0) {
fsrVideoProcessor.setSurfaceSize(frameWidth, frameHeight);
float requestedSharpness = fsrSharpness / 10f;
if (Float.compare(appliedFsrSharpness, requestedSharpness) != 0) {
fsrVideoProcessor.setSharpness(requestedSharpness);
appliedFsrSharpness = requestedSharpness;
}
int surfaceWidth = viewportWidth > 0 ? viewportWidth : frameWidth;
int surfaceHeight = viewportHeight > 0 ? viewportHeight : frameHeight;
if (surfaceWidth > 0 && surfaceHeight > 0
&& (surfaceWidth != appliedSurfaceWidth || surfaceHeight != appliedSurfaceHeight)) {
fsrVideoProcessor.setSurfaceSize(surfaceWidth, surfaceHeight);
appliedSurfaceWidth = surfaceWidth;
appliedSurfaceHeight = surfaceHeight;
}

boolean rendered = fsrVideoProcessor.draw(
Expand All @@ -667,10 +736,15 @@ private void handleDrawOes(Object[] args) {
texMatrix
);
if (!rendered) {
// Release FSR resources and keep using the stable fallback after a failed draw.
releaseDrawerResources();
fsrFallbackActive = true;
invokeFallbackDrawer("drawOes", args);
}
} catch (Throwable t) {
Log.e(TAG, "FSR draw failed, fallback to default OES drawer.", t);
releaseDrawerResources();
fsrFallbackActive = true;
invokeFallbackDrawer("drawOes", args);
}
}
Expand Down Expand Up @@ -711,7 +785,7 @@ private synchronized void ensureFsrInitialized() {

String extensions = GLES20.glGetString(GLES20.GL_EXTENSIONS);
fsrVideoProcessor.initialize(major, minor, extensions == null ? "" : extensions);
fsrVideoProcessor.setFsrEnabled(fsrEnabled);
applyEffectiveFsrEnabled();
fsrVideoProcessor.setSharpness(fsrSharpness / 10f);
fsrInitialized = true;
}
Expand Down Expand Up @@ -743,13 +817,21 @@ private void invokeFallbackDrawer(String methodName, Object[] args) {
if (drawer == null) {
return;
}

try {
Method target = findByNameAndArgCount(drawer.getClass(), methodName, args == null ? 0 : args.length);
Method target;
if ("drawOes".equals(methodName)) {
if (fallbackDrawOesMethod == null) {
fallbackDrawOesMethod = findByNameAndArgCount(drawer.getClass(), methodName, args == null ? 0 : args.length);
}
target = fallbackDrawOesMethod;
} else {
target = findByNameAndArgCount(drawer.getClass(), methodName, args == null ? 0 : args.length);
}
if (target == null) {
return;
}
target.invoke(drawer, args == null ? new Object[0] : args);

} catch (Throwable t) {
Log.e(TAG, "Fallback drawer invocation failed: " + methodName, t);
}
Expand All @@ -772,18 +854,26 @@ private synchronized void releaseDrawerResources() {
Log.w(TAG, "Failed to release FSR processor", t);
}
fsrInitialized = false;
fsrFallbackActive = false;
appliedFsrSharpness = Float.NaN;
appliedSurfaceWidth = -1;
appliedSurfaceHeight = -1;
}

if (fallbackDrawer != null) {
try {
Method release = findByNameAndArgCount(fallbackDrawer.getClass(), "release", 0);
if (release != null) {
release.invoke(fallbackDrawer);
if (fallbackReleaseMethod == null) {
fallbackReleaseMethod = findByNameAndArgCount(fallbackDrawer.getClass(), "release", 0);
}
if (fallbackReleaseMethod != null) {
fallbackReleaseMethod.invoke(fallbackDrawer);
}

} catch (Throwable t) {
Log.w(TAG, "Failed to release fallback drawer", t);
}
fallbackDrawer = null;
fallbackDrawOesMethod = null;
fallbackReleaseMethod = null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ public void setFsrEnabled(RTCFsrVideoView view, boolean enabled) {
view.setFsrEnabled(enabled);
}

@ReactProp(name = "autoDisableFsrOnLowMemory", defaultBoolean = false)
public void setAutoDisableFsrOnLowMemory(RTCFsrVideoView view, boolean enabled) {
view.setAutoDisableFsrOnLowMemory(enabled);
}

@ReactProp(name = "fsrSharpness", defaultFloat = 2f)
public void setFsrSharpness(RTCFsrVideoView view, float sharpness) {
view.setFsrSharpness(sharpness);
Expand Down
Loading