discord-jadx/app/src/main/java/org/webrtc/EglRenderer.java

727 lines
28 KiB
Java

package org.webrtc;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.SurfaceTexture;
import android.opengl.GLES20;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.view.Surface;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import h0.c.e;
import h0.c.f;
import h0.c.g;
import h0.c.h;
import h0.c.i;
import h0.c.j;
import h0.c.k;
import h0.c.l;
import h0.c.n0;
import java.nio.ByteBuffer;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.webrtc.EglBase;
import org.webrtc.GlUtil;
import org.webrtc.RendererCommon;
/* loaded from: classes3.dex */
public class EglRenderer implements VideoSink {
private static final long LOG_INTERVAL_SEC = 4;
private static final String TAG = "EglRenderer";
private final GlTextureFrameBuffer bitmapTextureFramebuffer;
private final Matrix drawMatrix;
@Nullable
private RendererCommon.GlDrawer drawer;
@Nullable
private EglBase eglBase;
private final EglSurfaceCreation eglSurfaceCreationRunnable;
private volatile ErrorCallback errorCallback;
private final Object fpsReductionLock;
private final VideoFrameDrawer frameDrawer;
private final ArrayList<FrameListenerAndParams> frameListeners;
private final Object frameLock;
private int framesDropped;
private int framesReceived;
private int framesRendered;
private final Object handlerLock;
private float layoutAspectRatio;
private final Object layoutLock;
private final Runnable logStatisticsRunnable;
private long minRenderPeriodNs;
private boolean mirrorHorizontally;
private boolean mirrorVertically;
public final String name;
private long nextFrameTimeNs;
@Nullable
private VideoFrame pendingFrame;
private long renderSwapBufferTimeNs;
@Nullable
private Handler renderThreadHandler;
private long renderTimeNs;
private final Object statisticsLock;
private long statisticsStartTimeNs;
private boolean usePresentationTimeStamp;
/* renamed from: org.webrtc.EglRenderer$1 reason: invalid class name */
/* loaded from: classes3.dex */
public class AnonymousClass1 implements Runnable {
public AnonymousClass1() {
}
@Override // java.lang.Runnable
public void run() {
EglRenderer.access$100(EglRenderer.this);
synchronized (EglRenderer.access$200(EglRenderer.this)) {
if (EglRenderer.access$300(EglRenderer.this) != null) {
EglRenderer.access$300(EglRenderer.this).removeCallbacks(EglRenderer.access$400(EglRenderer.this));
EglRenderer.access$300(EglRenderer.this).postDelayed(EglRenderer.access$400(EglRenderer.this), TimeUnit.SECONDS.toMillis(4L));
}
}
}
}
/* renamed from: org.webrtc.EglRenderer$2 reason: invalid class name */
/* loaded from: classes3.dex */
public class AnonymousClass2 implements Runnable {
public AnonymousClass2() {
}
@Override // java.lang.Runnable
public void run() {
synchronized (EglRenderer.access$200(EglRenderer.this)) {
EglRenderer.access$302(EglRenderer.this, null);
}
}
}
/* loaded from: classes3.dex */
public class EglSurfaceCreation implements Runnable {
private Object surface;
private EglSurfaceCreation() {
}
public /* synthetic */ EglSurfaceCreation(EglRenderer eglRenderer, AnonymousClass1 r2) {
this();
}
@Override // java.lang.Runnable
public synchronized void run() {
if (!(this.surface == null || EglRenderer.access$000(EglRenderer.this) == null || EglRenderer.access$000(EglRenderer.this).hasSurface())) {
Object obj = this.surface;
if (obj instanceof Surface) {
EglRenderer.access$000(EglRenderer.this).createSurface((Surface) this.surface);
} else if (obj instanceof SurfaceTexture) {
EglRenderer.access$000(EglRenderer.this).createSurface((SurfaceTexture) this.surface);
} else {
throw new IllegalStateException("Invalid surface: " + this.surface);
}
EglRenderer.access$000(EglRenderer.this).makeCurrent();
GLES20.glPixelStorei(3317, 1);
}
}
public synchronized void setSurface(Object obj) {
this.surface = obj;
}
}
/* loaded from: classes3.dex */
public interface ErrorCallback {
void onGlOutOfMemory();
}
/* loaded from: classes3.dex */
public interface FrameListener {
void onFrame(Bitmap bitmap);
}
/* loaded from: classes3.dex */
public static class FrameListenerAndParams {
public final boolean applyFpsReduction;
public final RendererCommon.GlDrawer drawer;
public final FrameListener listener;
public final float scale;
public FrameListenerAndParams(FrameListener frameListener, float f, RendererCommon.GlDrawer glDrawer, boolean z2) {
this.listener = frameListener;
this.scale = f;
this.drawer = glDrawer;
this.applyFpsReduction = z2;
}
}
/* loaded from: classes3.dex */
public static class HandlerWithExceptionCallback extends Handler {
private final Runnable exceptionCallback;
public HandlerWithExceptionCallback(Looper looper, Runnable runnable) {
super(looper);
this.exceptionCallback = runnable;
}
@Override // android.os.Handler
public void dispatchMessage(Message message) {
try {
super.dispatchMessage(message);
} catch (Exception e) {
Logging.e(EglRenderer.TAG, "Exception on EglRenderer thread", e);
this.exceptionCallback.run();
throw e;
}
}
}
public EglRenderer(String str) {
this(str, new VideoFrameDrawer());
}
public EglRenderer(String str, VideoFrameDrawer videoFrameDrawer) {
this.handlerLock = new Object();
this.frameListeners = new ArrayList<>();
this.fpsReductionLock = new Object();
this.drawMatrix = new Matrix();
this.frameLock = new Object();
this.layoutLock = new Object();
this.statisticsLock = new Object();
this.bitmapTextureFramebuffer = new GlTextureFrameBuffer(6408);
this.logStatisticsRunnable = new AnonymousClass1();
this.eglSurfaceCreationRunnable = new EglSurfaceCreation(this, null);
this.name = str;
this.frameDrawer = videoFrameDrawer;
}
public static /* synthetic */ EglBase access$000(EglRenderer eglRenderer) {
return eglRenderer.eglBase;
}
public static /* synthetic */ void access$100(EglRenderer eglRenderer) {
eglRenderer.logStatistics();
}
public static /* synthetic */ Object access$200(EglRenderer eglRenderer) {
return eglRenderer.handlerLock;
}
public static /* synthetic */ Handler access$300(EglRenderer eglRenderer) {
return eglRenderer.renderThreadHandler;
}
public static /* synthetic */ Handler access$302(EglRenderer eglRenderer, Handler handler) {
eglRenderer.renderThreadHandler = handler;
return handler;
}
public static /* synthetic */ Runnable access$400(EglRenderer eglRenderer) {
return eglRenderer.logStatisticsRunnable;
}
private String averageTimeAsString(long j, int i) {
if (i <= 0) {
return "NA";
}
return TimeUnit.NANOSECONDS.toMicros(j / i) + " us";
}
public static /* synthetic */ void c(EglRenderer eglRenderer) {
eglRenderer.renderFrameOnRenderThread();
}
/* JADX INFO: Access modifiers changed from: private */
/* renamed from: clearSurfaceOnRenderThread */
public void b(float f, float f2, float f3, float f4) {
EglBase eglBase = this.eglBase;
if (eglBase != null && eglBase.hasSurface()) {
logD("clearSurface");
GLES20.glClearColor(f, f2, f3, f4);
GLES20.glClear(16384);
this.eglBase.swapBuffers();
}
}
private void createEglSurfaceInternal(Object obj) {
this.eglSurfaceCreationRunnable.setSurface(obj);
postToRenderThread(this.eglSurfaceCreationRunnable);
}
/* JADX INFO: Access modifiers changed from: private */
/* renamed from: lambda$init$0 */
public void d(EglBase.Context context, int[] iArr) {
if (context == null) {
logD("EglBase10.create context");
Object obj = EglBase.lock;
this.eglBase = new EglBase10Impl(null, iArr);
return;
}
logD("EglBase.create shared context");
this.eglBase = n0.b(context, iArr);
}
private void logD(String str) {
Logging.d(TAG, this.name + str);
}
private void logE(String str, Throwable th) {
Logging.e(TAG, this.name + str, th);
}
private void logStatistics() {
DecimalFormat decimalFormat = new DecimalFormat("#.0");
long nanoTime = System.nanoTime();
synchronized (this.statisticsLock) {
long j = nanoTime - this.statisticsStartTimeNs;
if (j > 0 && !(this.minRenderPeriodNs == RecyclerView.FOREVER_NS && this.framesReceived == 0)) {
float nanos = ((float) (this.framesRendered * TimeUnit.SECONDS.toNanos(1L))) / ((float) j);
logD("Duration: " + TimeUnit.NANOSECONDS.toMillis(j) + " ms. Frames received: " + this.framesReceived + ". Dropped: " + this.framesDropped + ". Rendered: " + this.framesRendered + ". Render fps: " + decimalFormat.format(nanos) + ". Average render time: " + averageTimeAsString(this.renderTimeNs, this.framesRendered) + ". Average swapBuffer time: " + averageTimeAsString(this.renderSwapBufferTimeNs, this.framesRendered) + ".");
resetStatistics(nanoTime);
}
}
}
private void logW(String str) {
Logging.w(TAG, this.name + str);
}
private void notifyCallbacks(VideoFrame videoFrame, boolean z2) {
if (!this.frameListeners.isEmpty()) {
this.drawMatrix.reset();
this.drawMatrix.preTranslate(0.5f, 0.5f);
this.drawMatrix.preScale(this.mirrorHorizontally ? -1.0f : 1.0f, this.mirrorVertically ? -1.0f : 1.0f);
this.drawMatrix.preScale(1.0f, -1.0f);
this.drawMatrix.preTranslate(-0.5f, -0.5f);
Iterator<FrameListenerAndParams> it = this.frameListeners.iterator();
while (it.hasNext()) {
FrameListenerAndParams next = it.next();
if (z2 || !next.applyFpsReduction) {
it.remove();
int rotatedWidth = (int) (next.scale * videoFrame.getRotatedWidth());
int rotatedHeight = (int) (next.scale * videoFrame.getRotatedHeight());
if (rotatedWidth == 0 || rotatedHeight == 0) {
next.listener.onFrame(null);
} else {
this.bitmapTextureFramebuffer.setSize(rotatedWidth, rotatedHeight);
GLES20.glBindFramebuffer(36160, this.bitmapTextureFramebuffer.getFrameBufferId());
GLES20.glFramebufferTexture2D(36160, 36064, 3553, this.bitmapTextureFramebuffer.getTextureId(), 0);
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GLES20.glClear(16384);
this.frameDrawer.drawFrame(videoFrame, next.drawer, this.drawMatrix, 0, 0, rotatedWidth, rotatedHeight);
ByteBuffer allocateDirect = ByteBuffer.allocateDirect(rotatedWidth * rotatedHeight * 4);
GLES20.glViewport(0, 0, rotatedWidth, rotatedHeight);
GLES20.glReadPixels(0, 0, rotatedWidth, rotatedHeight, 6408, 5121, allocateDirect);
GLES20.glBindFramebuffer(36160, 0);
GlUtil.checkNoGLES2Error("EglRenderer.notifyCallbacks");
Bitmap createBitmap = Bitmap.createBitmap(rotatedWidth, rotatedHeight, Bitmap.Config.ARGB_8888);
createBitmap.copyPixelsFromBuffer(allocateDirect);
next.listener.onFrame(createBitmap);
}
}
}
}
}
private void postToRenderThread(Runnable runnable) {
synchronized (this.handlerLock) {
Handler handler = this.renderThreadHandler;
if (handler != null) {
handler.post(runnable);
}
}
}
private void renderFrameOnRenderThread() {
boolean z2;
boolean z3;
float f;
float f2;
float f3;
Throwable th;
GlUtil.GlOutOfMemoryException e;
synchronized (this.frameLock) {
VideoFrame videoFrame = this.pendingFrame;
if (videoFrame != null) {
this.pendingFrame = null;
EglBase eglBase = this.eglBase;
if (eglBase == null || !eglBase.hasSurface()) {
logD("Dropping frame - No surface");
videoFrame.release();
return;
}
synchronized (this.fpsReductionLock) {
long j = this.minRenderPeriodNs;
z2 = true;
if (j != RecyclerView.FOREVER_NS) {
if (j > 0) {
long nanoTime = System.nanoTime();
long j2 = this.nextFrameTimeNs;
if (nanoTime < j2) {
logD("Skipping frame rendering - fps reduction is active.");
} else {
long j3 = j2 + this.minRenderPeriodNs;
this.nextFrameTimeNs = j3;
this.nextFrameTimeNs = Math.max(j3, nanoTime);
}
}
z3 = true;
}
z3 = false;
}
long nanoTime2 = System.nanoTime();
float rotatedWidth = videoFrame.getRotatedWidth() / videoFrame.getRotatedHeight();
synchronized (this.layoutLock) {
f = this.layoutAspectRatio;
if (f == 0.0f) {
f = rotatedWidth;
}
}
float f4 = 1.0f;
if (rotatedWidth > f) {
f2 = f / rotatedWidth;
f3 = 1.0f;
} else {
f3 = rotatedWidth / f;
f2 = 1.0f;
}
this.drawMatrix.reset();
this.drawMatrix.preTranslate(0.5f, 0.5f);
Matrix matrix = this.drawMatrix;
float f5 = this.mirrorHorizontally ? -1.0f : 1.0f;
if (this.mirrorVertically) {
f4 = -1.0f;
}
matrix.preScale(f5, f4);
this.drawMatrix.preScale(f2, f3);
this.drawMatrix.preTranslate(-0.5f, -0.5f);
try {
try {
notifyCallbacks(videoFrame, z3);
if (z3) {
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GLES20.glClear(16384);
this.frameDrawer.drawFrame(videoFrame, this.drawer, this.drawMatrix, 0, 0, this.eglBase.surfaceWidth(), this.eglBase.surfaceHeight());
long nanoTime3 = System.nanoTime();
try {
if (this.usePresentationTimeStamp) {
long timestampNs = videoFrame.getTimestampNs();
videoFrame.release();
this.eglBase.swapBuffers(timestampNs);
} else {
videoFrame.release();
this.eglBase.swapBuffers();
}
long nanoTime4 = System.nanoTime();
synchronized (this.statisticsLock) {
this.framesRendered++;
this.renderTimeNs = (nanoTime4 - nanoTime2) + this.renderTimeNs;
this.renderSwapBufferTimeNs = (nanoTime4 - nanoTime3) + this.renderSwapBufferTimeNs;
}
z2 = false;
} catch (GlUtil.GlOutOfMemoryException e2) {
e = e2;
z2 = false;
logE("Error while drawing frame", e);
ErrorCallback errorCallback = this.errorCallback;
if (errorCallback != null) {
errorCallback.onGlOutOfMemory();
}
this.drawer.release();
this.frameDrawer.release();
this.bitmapTextureFramebuffer.release();
if (!z2) {
return;
}
videoFrame.release();
} catch (Throwable th2) {
th = th2;
z2 = false;
if (z2) {
videoFrame.release();
}
throw th;
}
}
notifyCallbacks(videoFrame, z3);
if (!z2) {
return;
}
} catch (Throwable th3) {
th = th3;
}
} catch (GlUtil.GlOutOfMemoryException e3) {
e = e3;
}
videoFrame.release();
}
}
}
private void resetStatistics(long j) {
synchronized (this.statisticsLock) {
this.statisticsStartTimeNs = j;
this.framesReceived = 0;
this.framesDropped = 0;
this.framesRendered = 0;
this.renderTimeNs = 0L;
this.renderSwapBufferTimeNs = 0L;
}
}
public /* synthetic */ void a(RendererCommon.GlDrawer glDrawer, FrameListener frameListener, float f, boolean z2) {
if (glDrawer == null) {
glDrawer = this.drawer;
}
this.frameListeners.add(new FrameListenerAndParams(frameListener, f, glDrawer, z2));
}
public void addFrameListener(FrameListener frameListener, float f) {
addFrameListener(frameListener, f, null, false);
}
public void addFrameListener(FrameListener frameListener, float f, RendererCommon.GlDrawer glDrawer) {
addFrameListener(frameListener, f, glDrawer, false);
}
public void addFrameListener(FrameListener frameListener, float f, @Nullable RendererCommon.GlDrawer glDrawer, boolean z2) {
postToRenderThread(new l(this, glDrawer, frameListener, f, z2));
}
public void clearImage() {
clearImage(0.0f, 0.0f, 0.0f, 0.0f);
}
public void clearImage(float f, float f2, float f3, float f4) {
synchronized (this.handlerLock) {
Handler handler = this.renderThreadHandler;
if (handler != null) {
handler.postAtFrontOfQueue(new f(this, f, f2, f3, f4));
}
}
}
public void createEglSurface(SurfaceTexture surfaceTexture) {
createEglSurfaceInternal(surfaceTexture);
}
public void createEglSurface(Surface surface) {
createEglSurfaceInternal(surface);
}
public void disableFpsReduction() {
setFpsReduction(Float.POSITIVE_INFINITY);
}
public /* synthetic */ void e(CountDownLatch countDownLatch) {
synchronized (EglBase.lock) {
GLES20.glUseProgram(0);
}
RendererCommon.GlDrawer glDrawer = this.drawer;
if (glDrawer != null) {
glDrawer.release();
this.drawer = null;
}
this.frameDrawer.release();
this.bitmapTextureFramebuffer.release();
if (this.eglBase != null) {
logD("eglBase detach and release.");
this.eglBase.detachCurrent();
this.eglBase.release();
this.eglBase = null;
}
this.frameListeners.clear();
countDownLatch.countDown();
}
public /* synthetic */ void f(Looper looper) {
logD("Quitting render thread.");
looper.quit();
}
public /* synthetic */ void g(Runnable runnable) {
EglBase eglBase = this.eglBase;
if (eglBase != null) {
eglBase.detachCurrent();
this.eglBase.releaseSurface();
}
runnable.run();
}
public /* synthetic */ void h(CountDownLatch countDownLatch, FrameListener frameListener) {
countDownLatch.countDown();
Iterator<FrameListenerAndParams> it = this.frameListeners.iterator();
while (it.hasNext()) {
if (it.next().listener == frameListener) {
it.remove();
}
}
}
public void init(@Nullable EglBase.Context context, int[] iArr, RendererCommon.GlDrawer glDrawer) {
init(context, iArr, glDrawer, false);
}
public void init(@Nullable EglBase.Context context, int[] iArr, RendererCommon.GlDrawer glDrawer, boolean z2) {
synchronized (this.handlerLock) {
if (this.renderThreadHandler == null) {
logD("Initializing EglRenderer");
this.drawer = glDrawer;
this.usePresentationTimeStamp = z2;
HandlerThread handlerThread = new HandlerThread(this.name + TAG);
handlerThread.start();
HandlerWithExceptionCallback handlerWithExceptionCallback = new HandlerWithExceptionCallback(handlerThread.getLooper(), new AnonymousClass2());
this.renderThreadHandler = handlerWithExceptionCallback;
ThreadUtils.invokeAtFrontUninterruptibly(handlerWithExceptionCallback, new j(this, context, iArr));
this.renderThreadHandler.post(this.eglSurfaceCreationRunnable);
resetStatistics(System.nanoTime());
this.renderThreadHandler.postDelayed(this.logStatisticsRunnable, TimeUnit.SECONDS.toMillis(4L));
} else {
throw new IllegalStateException(this.name + "Already initialized");
}
}
}
@Override // org.webrtc.VideoSink
public void onFrame(VideoFrame videoFrame) {
boolean z2;
synchronized (this.statisticsLock) {
this.framesReceived++;
}
synchronized (this.handlerLock) {
if (this.renderThreadHandler == null) {
logD("Dropping frame - Not initialized or already released.");
return;
}
synchronized (this.frameLock) {
VideoFrame videoFrame2 = this.pendingFrame;
z2 = videoFrame2 != null;
if (z2) {
videoFrame2.release();
}
this.pendingFrame = videoFrame;
videoFrame.retain();
this.renderThreadHandler.post(new i(this));
}
if (z2) {
synchronized (this.statisticsLock) {
this.framesDropped++;
}
}
}
}
public void pauseVideo() {
setFpsReduction(0.0f);
}
public void printStackTrace() {
synchronized (this.handlerLock) {
Handler handler = this.renderThreadHandler;
Thread thread = handler == null ? null : handler.getLooper().getThread();
if (thread != null) {
StackTraceElement[] stackTrace = thread.getStackTrace();
if (stackTrace.length > 0) {
logW("EglRenderer stack trace:");
for (StackTraceElement stackTraceElement : stackTrace) {
logW(stackTraceElement.toString());
}
}
}
}
}
public void release() {
logD("Releasing.");
CountDownLatch countDownLatch = new CountDownLatch(1);
synchronized (this.handlerLock) {
Handler handler = this.renderThreadHandler;
if (handler == null) {
logD("Already released");
return;
}
handler.removeCallbacks(this.logStatisticsRunnable);
this.renderThreadHandler.postAtFrontOfQueue(new h(this, countDownLatch));
this.renderThreadHandler.post(new k(this, this.renderThreadHandler.getLooper()));
this.renderThreadHandler = null;
ThreadUtils.awaitUninterruptibly(countDownLatch);
synchronized (this.frameLock) {
VideoFrame videoFrame = this.pendingFrame;
if (videoFrame != null) {
videoFrame.release();
this.pendingFrame = null;
}
}
logD("Releasing done.");
}
}
public void releaseEglSurface(Runnable runnable) {
this.eglSurfaceCreationRunnable.setSurface(null);
synchronized (this.handlerLock) {
Handler handler = this.renderThreadHandler;
if (handler != null) {
handler.removeCallbacks(this.eglSurfaceCreationRunnable);
this.renderThreadHandler.postAtFrontOfQueue(new e(this, runnable));
return;
}
runnable.run();
}
}
public void removeFrameListener(FrameListener frameListener) {
CountDownLatch countDownLatch = new CountDownLatch(1);
synchronized (this.handlerLock) {
if (this.renderThreadHandler != null) {
if (Thread.currentThread() != this.renderThreadHandler.getLooper().getThread()) {
postToRenderThread(new g(this, countDownLatch, frameListener));
ThreadUtils.awaitUninterruptibly(countDownLatch);
return;
}
throw new RuntimeException("removeFrameListener must not be called on the render thread.");
}
}
}
public void setErrorCallback(ErrorCallback errorCallback) {
this.errorCallback = errorCallback;
}
public void setFpsReduction(float f) {
logD("setFpsReduction: " + f);
synchronized (this.fpsReductionLock) {
long j = this.minRenderPeriodNs;
if (f <= 0.0f) {
this.minRenderPeriodNs = RecyclerView.FOREVER_NS;
} else {
this.minRenderPeriodNs = ((float) TimeUnit.SECONDS.toNanos(1L)) / f;
}
if (this.minRenderPeriodNs != j) {
this.nextFrameTimeNs = System.nanoTime();
}
}
}
public void setLayoutAspectRatio(float f) {
logD("setLayoutAspectRatio: " + f);
synchronized (this.layoutLock) {
this.layoutAspectRatio = f;
}
}
public void setMirror(boolean z2) {
logD("setMirrorHorizontally: " + z2);
synchronized (this.layoutLock) {
this.mirrorHorizontally = z2;
}
}
public void setMirrorVertically(boolean z2) {
logD("setMirrorVertically: " + z2);
synchronized (this.layoutLock) {
this.mirrorVertically = z2;
}
}
}