From 013812fb55a89e7aec90b6df3c0850f0863aed92 Mon Sep 17 00:00:00 2001 From: pedro Date: Tue, 23 Apr 2024 12:06:12 +0200 Subject: [PATCH 1/2] try to fix error on stopSources --- .../encoder/input/gl/SurfaceManager.java | 12 ++++---- .../encoder/input/gl/render/MainRender.kt | 10 ++++--- .../java/com/pedro/library/base/StreamBase.kt | 8 ++--- .../pedro/library/view/GlStreamInterface.kt | 30 +++++++++++-------- .../com/pedro/library/view/OpenGlView.java | 12 ++++---- 5 files changed, 42 insertions(+), 30 deletions(-) diff --git a/encoder/src/main/java/com/pedro/encoder/input/gl/SurfaceManager.java b/encoder/src/main/java/com/pedro/encoder/input/gl/SurfaceManager.java index c03b9959e..4f40d3c8c 100644 --- a/encoder/src/main/java/com/pedro/encoder/input/gl/SurfaceManager.java +++ b/encoder/src/main/java/com/pedro/encoder/input/gl/SurfaceManager.java @@ -30,6 +30,8 @@ import com.pedro.encoder.utils.gl.GlUtil; +import java.util.concurrent.atomic.AtomicBoolean; + /** * Created by pedro on 9/09/17. */ @@ -44,10 +46,10 @@ public class SurfaceManager { private EGLContext eglContext = EGL14.EGL_NO_CONTEXT; private EGLSurface eglSurface = EGL14.EGL_NO_SURFACE; private EGLDisplay eglDisplay = EGL14.EGL_NO_DISPLAY; - private volatile boolean isReady = false; + private final AtomicBoolean isReady = new AtomicBoolean(false); public boolean isReady() { - return isReady; + return isReady.get(); } public void makeCurrent() { @@ -74,7 +76,7 @@ public void setPresentationTime(long nsecs) { * Prepares EGL. We want a GLES 2.0 context and a surface that supports recording. */ public void eglSetup(int width, int height, Surface surface, EGLContext eglSharedContext) { - if (isReady) { + if (isReady()) { Log.e(TAG, "already ready, ignored"); return; } @@ -155,7 +157,7 @@ public void eglSetup(int width, int height, Surface surface, EGLContext eglShare eglSurface = EGL14.eglCreateWindowSurface(eglDisplay, configs[0], surface, surfaceAttribs, 0); } GlUtil.checkEglError("eglCreateWindowSurface"); - isReady = true; + isReady.set(true); Log.i(TAG, "GL initialized"); } @@ -194,10 +196,10 @@ public void release() { eglDisplay = EGL14.EGL_NO_DISPLAY; eglContext = EGL14.EGL_NO_CONTEXT; eglSurface = EGL14.EGL_NO_SURFACE; - isReady = false; } else { Log.e(TAG, "GL already released"); } + isReady.set(false); } public EGLContext getEglContext() { diff --git a/encoder/src/main/java/com/pedro/encoder/input/gl/render/MainRender.kt b/encoder/src/main/java/com/pedro/encoder/input/gl/render/MainRender.kt index 66052bae5..8fc3d7a59 100644 --- a/encoder/src/main/java/com/pedro/encoder/input/gl/render/MainRender.kt +++ b/encoder/src/main/java/com/pedro/encoder/input/gl/render/MainRender.kt @@ -24,6 +24,7 @@ import androidx.annotation.RequiresApi import com.pedro.encoder.input.gl.FilterAction import com.pedro.encoder.input.gl.render.filters.BaseFilterRender import com.pedro.encoder.utils.gl.AspectRatioMode +import java.util.concurrent.atomic.AtomicBoolean /** * Created by pedro on 20/3/22. @@ -38,8 +39,7 @@ class MainRender { private var previewHeight = 0 private var context: Context? = null private var filterRenders: MutableList = ArrayList() - @Volatile - var isReady = false + private val running = AtomicBoolean(false) fun initGl(context: Context, encoderWidth: Int, encoderHeight: Int, previewWidth: Int, previewHeight: Int) { this.context = context @@ -51,9 +51,11 @@ class MainRender { screenRender.setStreamSize(encoderWidth, encoderHeight) screenRender.setTexId(cameraRender.texId) screenRender.initGl(context) - isReady = true + running.set(true) } + fun isReady(): Boolean = running.get() + fun drawOffScreen() { cameraRender.draw() for (baseFilterRender in filterRenders) baseFilterRender.draw() @@ -77,7 +79,7 @@ class MainRender { } fun release() { - isReady = false + running.set(false) cameraRender.release() for (baseFilterRender in filterRenders) baseFilterRender.release() filterRenders.clear() diff --git a/library/src/main/java/com/pedro/library/base/StreamBase.kt b/library/src/main/java/com/pedro/library/base/StreamBase.kt index e4e921917..87a871492 100644 --- a/library/src/main/java/com/pedro/library/base/StreamBase.kt +++ b/library/src/main/java/com/pedro/library/base/StreamBase.kt @@ -266,7 +266,7 @@ abstract class StreamBase( if (!surface.isValid) throw IllegalArgumentException("Make sure the Surface is valid") if (isOnPreview) throw IllegalStateException("Preview already started, stopPreview before startPreview again") isOnPreview = true - if (!glInterface.running) glInterface.start() + if (!glInterface.isRunning) glInterface.start() if (!videoSource.isRunning()) { videoSource.start(glInterface.surfaceTexture) } @@ -371,7 +371,7 @@ abstract class StreamBase( protected fun getVideoFps() = videoEncoder.fps private fun startSources() { - if (!glInterface.running) glInterface.start() + if (!glInterface.isRunning) glInterface.start() if (!videoSource.isRunning()) { videoSource.start(glInterface.surfaceTexture) } @@ -384,10 +384,10 @@ abstract class StreamBase( private fun stopSources() { if (!isOnPreview) videoSource.stop() audioSource.stop() - videoEncoder.stop() - audioEncoder.stop() glInterface.removeMediaCodecSurface() if (!isOnPreview) glInterface.stop() + videoEncoder.stop() + audioEncoder.stop() if (!isRecording) recordController.resetFormats() } diff --git a/library/src/main/java/com/pedro/library/view/GlStreamInterface.kt b/library/src/main/java/com/pedro/library/view/GlStreamInterface.kt index 3f8fa33cc..c1f0e335d 100644 --- a/library/src/main/java/com/pedro/library/view/GlStreamInterface.kt +++ b/library/src/main/java/com/pedro/library/view/GlStreamInterface.kt @@ -21,6 +21,7 @@ import android.graphics.Point import android.graphics.SurfaceTexture import android.graphics.SurfaceTexture.OnFrameAvailableListener import android.os.Build +import android.util.Log import android.view.Surface import androidx.annotation.RequiresApi import com.pedro.common.secureSubmit @@ -38,6 +39,7 @@ import java.util.concurrent.BlockingQueue import java.util.concurrent.ExecutorService import java.util.concurrent.Executors import java.util.concurrent.LinkedBlockingQueue +import java.util.concurrent.atomic.AtomicBoolean /** @@ -47,9 +49,7 @@ import java.util.concurrent.LinkedBlockingQueue class GlStreamInterface(private val context: Context): OnFrameAvailableListener, GlInterface { private var takePhotoCallback: TakePhotoCallback? = null - @Volatile - var running = false - private set + private val running = AtomicBoolean(false) private val surfaceManager = SurfaceManager() private val surfaceManagerEncoder = SurfaceManager() private val surfaceManagerPhoto = SurfaceManager() @@ -108,7 +108,7 @@ class GlStreamInterface(private val context: Context): OnFrameAvailableListener, setForceRender(enabled, 5) } - override fun isRunning(): Boolean = running + override fun isRunning(): Boolean = running.get() override fun getSurfaceTexture(): SurfaceTexture { return mainRender.getSurfaceTexture() @@ -119,6 +119,7 @@ class GlStreamInterface(private val context: Context): OnFrameAvailableListener, } override fun addMediaCodecSurface(surface: Surface) { + Log.e("Pedro", "addMediaCodecSurface") executor?.secureSubmit { if (surfaceManager.isReady) { surfaceManagerEncoder.release() @@ -128,6 +129,7 @@ class GlStreamInterface(private val context: Context): OnFrameAvailableListener, } override fun removeMediaCodecSurface() { + Log.e("Pedro", "removeMediaCodecSurface") executor?.secureSubmit { surfaceManagerEncoder.release() } @@ -138,6 +140,7 @@ class GlStreamInterface(private val context: Context): OnFrameAvailableListener, } override fun start() { + Log.e("Pedro", "start glInterface") executor = Executors.newSingleThreadExecutor() executor?.secureSubmit { surfaceManager.release() @@ -146,7 +149,7 @@ class GlStreamInterface(private val context: Context): OnFrameAvailableListener, mainRender.initGl(context, encoderWidth, encoderHeight, encoderWidth, encoderHeight) surfaceManagerPhoto.release() surfaceManagerPhoto.eglSetup(encoderWidth, encoderHeight, surfaceManager) - running = true + running.set(true) mainRender.getSurfaceTexture().setOnFrameAvailableListener(this) forceRender.start { executor?.execute { draw(true) } } if (autoHandleOrientation) sensorRotationManager.start() @@ -154,7 +157,8 @@ class GlStreamInterface(private val context: Context): OnFrameAvailableListener, } override fun stop() { - running = false + Log.e("Pedro", "stop glInterface") + running.set(false) executor?.secureSubmit { forceRender.stop() sensorRotationManager.stop() @@ -168,17 +172,18 @@ class GlStreamInterface(private val context: Context): OnFrameAvailableListener, } private fun draw(forced: Boolean) { - if (!running || fpsLimiter.limitFPS()) return + Log.e("Pedro", "id: ${Thread.currentThread().id}, name: ${Thread.currentThread().name}") + if (!isRunning || fpsLimiter.limitFPS()) return if (!forced) forceRender.frameAvailable() - if (surfaceManager.isReady && mainRender.isReady) { + if (surfaceManager.isReady && mainRender.isReady()) { surfaceManager.makeCurrent() mainRender.updateFrame() mainRender.drawOffScreen() surfaceManager.swapBuffer() } - if (!filterQueue.isEmpty() && mainRender.isReady) { + if (!filterQueue.isEmpty() && mainRender.isReady()) { try { val filter = filterQueue.take() mainRender.setFilterAction(filter.filterAction, filter.position, filter.baseFilterRender) @@ -194,7 +199,7 @@ class GlStreamInterface(private val context: Context): OnFrameAvailableListener, OrientationForced.NONE -> isPortrait } // render VideoEncoder (stream and record) - if (surfaceManagerEncoder.isReady && mainRender.isReady) { + if (surfaceManagerEncoder.isReady && mainRender.isReady()) { val w = if (muteVideo) 0 else encoderWidth val h = if (muteVideo) 0 else encoderHeight surfaceManagerEncoder.makeCurrent() @@ -203,7 +208,7 @@ class GlStreamInterface(private val context: Context): OnFrameAvailableListener, surfaceManagerEncoder.swapBuffer() } //render surface photo if request photo - if (takePhotoCallback != null && surfaceManagerPhoto.isReady && mainRender.isReady) { + if (takePhotoCallback != null && surfaceManagerPhoto.isReady && mainRender.isReady()) { surfaceManagerPhoto.makeCurrent() mainRender.drawScreen(encoderWidth, encoderHeight, AspectRatioMode.NONE, streamOrientation, isStreamVerticalFlip, isStreamHorizontalFlip) @@ -212,7 +217,7 @@ class GlStreamInterface(private val context: Context): OnFrameAvailableListener, surfaceManagerPhoto.swapBuffer() } // render preview - if (surfaceManagerPreview.isReady && mainRender.isReady) { + if (surfaceManagerPreview.isReady && mainRender.isReady()) { val w = if (previewWidth == 0) encoderWidth else previewWidth val h = if (previewHeight == 0) encoderHeight else previewHeight surfaceManagerPreview.makeCurrent() @@ -223,6 +228,7 @@ class GlStreamInterface(private val context: Context): OnFrameAvailableListener, } override fun onFrameAvailable(surfaceTexture: SurfaceTexture?) { + if (!isRunning) return executor?.execute { draw(false) } } diff --git a/library/src/main/java/com/pedro/library/view/OpenGlView.java b/library/src/main/java/com/pedro/library/view/OpenGlView.java index 97df778ab..40bffdbff 100644 --- a/library/src/main/java/com/pedro/library/view/OpenGlView.java +++ b/library/src/main/java/com/pedro/library/view/OpenGlView.java @@ -45,6 +45,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.atomic.AtomicBoolean; /** * Created by pedro on 10/03/18. @@ -54,7 +55,7 @@ public class OpenGlView extends SurfaceView implements GlInterface, SurfaceTexture.OnFrameAvailableListener, SurfaceHolder.Callback { - private volatile boolean running = false; + private AtomicBoolean running = new AtomicBoolean(false); private final MainRender mainRender = new MainRender(); private final SurfaceManager surfaceManagerPhoto = new SurfaceManager(); private final SurfaceManager surfaceManager = new SurfaceManager(); @@ -213,7 +214,7 @@ public void setForceRender(boolean enabled) { @Override public boolean isRunning() { - return running; + return running.get(); } @Override @@ -233,7 +234,7 @@ public void takePhoto(TakePhotoCallback takePhotoCallback) { } private void draw(boolean forced) { - if (!running || fpsLimiter.limitFPS()) return; + if (!isRunning() || fpsLimiter.limitFPS()) return; if (!forced) forceRenderer.frameAvailable(); if (surfaceManager.isReady() && mainRender.isReady()) { @@ -311,7 +312,7 @@ public void start() { mainRender.initGl(getContext(), encoderWidth, encoderHeight, encoderWidth, encoderHeight); surfaceManagerPhoto.release(); surfaceManagerPhoto.eglSetup(encoderWidth, encoderHeight, surfaceManager); - running = true; + running.set(true); mainRender.getSurfaceTexture().setOnFrameAvailableListener(this); forceRenderer.start(() -> { ExecutorService ex = this.executor; @@ -325,7 +326,7 @@ public void start() { @Override public void stop() { - running = false; + running.set(false); ExecutorService executor = this.executor; if (executor == null) return; ExtensionsKt.secureSubmit(executor, () -> { @@ -342,6 +343,7 @@ public void stop() { @Override public void onFrameAvailable(SurfaceTexture surfaceTexture) { + if (!isRunning()) return; ExecutorService ex = this.executor; if (ex == null) return; ex.execute(() -> draw(false)); From f90ea1ba9648a9ac609eec4804985002aa74a913 Mon Sep 17 00:00:00 2001 From: pedro Date: Tue, 23 Apr 2024 18:08:25 +0200 Subject: [PATCH 2/2] remove logs --- .../main/java/com/pedro/library/view/GlStreamInterface.kt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/library/src/main/java/com/pedro/library/view/GlStreamInterface.kt b/library/src/main/java/com/pedro/library/view/GlStreamInterface.kt index c1f0e335d..33b1d9e09 100644 --- a/library/src/main/java/com/pedro/library/view/GlStreamInterface.kt +++ b/library/src/main/java/com/pedro/library/view/GlStreamInterface.kt @@ -21,7 +21,6 @@ import android.graphics.Point import android.graphics.SurfaceTexture import android.graphics.SurfaceTexture.OnFrameAvailableListener import android.os.Build -import android.util.Log import android.view.Surface import androidx.annotation.RequiresApi import com.pedro.common.secureSubmit @@ -119,7 +118,6 @@ class GlStreamInterface(private val context: Context): OnFrameAvailableListener, } override fun addMediaCodecSurface(surface: Surface) { - Log.e("Pedro", "addMediaCodecSurface") executor?.secureSubmit { if (surfaceManager.isReady) { surfaceManagerEncoder.release() @@ -129,7 +127,6 @@ class GlStreamInterface(private val context: Context): OnFrameAvailableListener, } override fun removeMediaCodecSurface() { - Log.e("Pedro", "removeMediaCodecSurface") executor?.secureSubmit { surfaceManagerEncoder.release() } @@ -140,7 +137,6 @@ class GlStreamInterface(private val context: Context): OnFrameAvailableListener, } override fun start() { - Log.e("Pedro", "start glInterface") executor = Executors.newSingleThreadExecutor() executor?.secureSubmit { surfaceManager.release() @@ -157,7 +153,6 @@ class GlStreamInterface(private val context: Context): OnFrameAvailableListener, } override fun stop() { - Log.e("Pedro", "stop glInterface") running.set(false) executor?.secureSubmit { forceRender.stop() @@ -172,7 +167,6 @@ class GlStreamInterface(private val context: Context): OnFrameAvailableListener, } private fun draw(forced: Boolean) { - Log.e("Pedro", "id: ${Thread.currentThread().id}, name: ${Thread.currentThread().name}") if (!isRunning || fpsLimiter.limitFPS()) return if (!forced) forceRender.frameAvailable()