@@ -26,13 +26,13 @@ import androidx.annotation.IntRange
2626import androidx.concurrent.futures.CallbackToFutureAdapter
2727import com.google.common.util.concurrent.ListenableFuture
2828import io.github.thibaultbee.streampack.core.elements.processing.video.outputs.ISurfaceOutput
29+ import io.github.thibaultbee.streampack.core.elements.processing.video.outputs.SurfaceOutput
2930import io.github.thibaultbee.streampack.core.elements.processing.video.utils.GLUtils
3031import io.github.thibaultbee.streampack.core.elements.processing.video.utils.extensions.preRotate
3132import io.github.thibaultbee.streampack.core.elements.processing.video.utils.extensions.preVerticalFlip
3233import io.github.thibaultbee.streampack.core.elements.utils.av.video.DynamicRangeProfile
3334import io.github.thibaultbee.streampack.core.elements.utils.extensions.rotate
3435import io.github.thibaultbee.streampack.core.logger.Logger
35- import java.io.IOException
3636import java.util.concurrent.atomic.AtomicBoolean
3737
3838
@@ -119,7 +119,7 @@ private class DefaultSurfaceProcessor(
119119
120120 executeSafely {
121121 if (! surfaceOutputs.contains(surfaceOutput)) {
122- renderer.registerOutputSurface(surfaceOutput.descriptor. surface)
122+ renderer.registerOutputSurface(surfaceOutput.surface)
123123 surfaceOutputs.add(surfaceOutput)
124124 } else {
125125 Logger .w(TAG , " Surface already added" )
@@ -129,7 +129,7 @@ private class DefaultSurfaceProcessor(
129129
130130 private fun removeOutputSurfaceInternal (surfaceOutput : ISurfaceOutput ) {
131131 if (surfaceOutputs.contains(surfaceOutput)) {
132- renderer.unregisterOutputSurface(surfaceOutput.descriptor. surface)
132+ renderer.unregisterOutputSurface(surfaceOutput.surface)
133133 surfaceOutputs.remove(surfaceOutput)
134134 } else {
135135 Logger .w(TAG , " Surface not found" )
@@ -153,7 +153,7 @@ private class DefaultSurfaceProcessor(
153153
154154 executeSafely {
155155 val surfaceOutput =
156- surfaceOutputs.firstOrNull { it.descriptor. surface == surface }
156+ surfaceOutputs.firstOrNull { it.surface == surface }
157157 if (surfaceOutput != null ) {
158158 removeOutputSurfaceInternal(surfaceOutput)
159159 } else {
@@ -164,7 +164,7 @@ private class DefaultSurfaceProcessor(
164164
165165 private fun removeAllOutputSurfacesInternal () {
166166 surfaceOutputs.forEach { surfaceOutput ->
167- renderer.unregisterOutputSurface(surfaceOutput.descriptor. surface)
167+ renderer.unregisterOutputSurface(surfaceOutput.surface)
168168 }
169169 surfaceOutputs.clear()
170170 }
@@ -226,15 +226,17 @@ private class DefaultSurfaceProcessor(
226226
227227 val timestamp =
228228 surfaceTexture.timestamp + (surfaceInputsTimestampInNsMap[surfaceTexture] ? : 0L )
229- surfaceOutputs.filter { it.isStreaming() } .forEach {
229+ surfaceOutputs.filterIsInstance< SurfaceOutput >() .forEach {
230230 try {
231231 it.updateTransformMatrix(surfaceOutputMatrix, textureMatrix)
232- renderer.render(
233- timestamp,
234- surfaceOutputMatrix,
235- it.descriptor.surface,
236- it.viewportRect
237- )
232+ if (it.isStreaming()) {
233+ renderer.render(
234+ timestamp,
235+ surfaceOutputMatrix,
236+ it.surface,
237+ it.viewportRect
238+ )
239+ }
238240 } catch (t: Throwable ) {
239241 Logger .e(TAG , " Error while rendering frame" , t)
240242 }
@@ -243,14 +245,14 @@ private class DefaultSurfaceProcessor(
243245 // Surface, size and transform matrix for JPEG Surface if exists
244246 if (pendingSnapshots.isNotEmpty()) {
245247 try {
246- val first = surfaceOutputs.first()
247- val snapshotOutput = Pair (
248- first.descriptor.resolution,
249- surfaceOutputMatrix.clone()
250- )
248+ val bitmapSurface =
249+ surfaceOutputs.maxByOrNull { it.resolution.width * it.resolution.height }
250+ ? : throw IllegalStateException (
251+ " No output surface available for snapshot "
252+ )
251253
252254 // Execute all pending snapshots.
253- takeSnapshot(snapshotOutput )
255+ takeSnapshot(bitmapSurface.resolution, surfaceOutputMatrix.clone() )
254256 } catch (e: RuntimeException ) {
255257 // Propagates error back to the app if failed to take snapshot.
256258 failAllPendingSnapshots(e)
@@ -261,36 +263,39 @@ private class DefaultSurfaceProcessor(
261263 /* *
262264 * Takes a snapshot of the current frame and draws it to given JPEG surface.
263265 *
264- * @param snapshotOutput The <Surface size, transform matrix> pair for drawing.
266+ * @param snapshotSize The size of the snapshot.
267+ * @param snapshotTransform The GL transform matrix to apply to the snapshot.
265268 */
266- private fun takeSnapshot (snapshotOutput : Pair < Size , FloatArray > ) {
269+ private fun takeSnapshot (snapshotSize : Size , snapshotTransform : FloatArray ) {
267270 if (pendingSnapshots.isEmpty()) {
268271 // No pending snapshot requests, do nothing.
269272 return
270273 }
271274
272- // Write to JPEG surface , once for each snapshot request.
275+ // Write to Bitmap , once for each snapshot request.
273276 try {
274277 for (pendingSnapshot in pendingSnapshots) {
275- val (size, transform) = snapshotOutput
276-
277- // Take a snapshot of the current frame.
278- val bitmap = getBitmap(size, transform, pendingSnapshot.rotationDegrees)
279-
280- // Complete the snapshot request.
281- pendingSnapshot.completer.set(bitmap)
278+ try {
279+ // Take a snapshot of the current frame.
280+ val bitmap =
281+ getBitmap(snapshotSize, snapshotTransform, pendingSnapshot.rotationDegrees)
282+
283+ // Complete the snapshot request.
284+ pendingSnapshot.completer.set(bitmap)
285+ } catch (t: Throwable ) {
286+ // Propagate error back to the app if failed to take snapshot.
287+ pendingSnapshot.completer.setException(t)
288+ }
282289 }
290+ } finally {
283291 pendingSnapshots.clear()
284- } catch (e: IOException ) {
285- failAllPendingSnapshots(e)
286292 }
287293 }
288294
289295 private fun failAllPendingSnapshots (throwable : Throwable ) {
290296 for (pendingSnapshot in pendingSnapshots) {
291297 pendingSnapshot.completer.setException(throwable)
292298 }
293- pendingSnapshots.clear()
294299 }
295300
296301 private fun getBitmap (
0 commit comments