From 913b00f8b876e29af91677ef61b3eb35d6853e6e Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Mon, 13 Mar 2023 05:59:34 +0100 Subject: GLMediaPlayer: Overhaul and simplify states, allow usage before stream ready showing test-texture. Adding stop(); (API Change) - allow multiple initGL(..) @ uninitialized and initialized - allows usage before stream is ready - using a test-texture @ uninitialized - adding stop() API change - initStream() -> playStream() - play() -> resume() FFMPEG: Added 'ready' check for robustness --- .../com/jogamp/opengl/util/av/GLMediaPlayer.java | 45 ++++++++++++++-------- 1 file changed, 28 insertions(+), 17 deletions(-) (limited to 'src/jogl/classes/com') diff --git a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java index c2de32372..5740dae4b 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java +++ b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java @@ -37,6 +37,7 @@ import com.jogamp.common.net.Uri; import com.jogamp.opengl.util.texture.Texture; import com.jogamp.opengl.util.texture.TextureSequence; import com.jogamp.opengl.util.TimeFrameI; +import com.jogamp.opengl.util.av.GLMediaPlayer.State; /** * GLMediaPlayer interface specifies a {@link TextureSequence} state machine @@ -45,7 +46,7 @@ import com.jogamp.opengl.util.TimeFrameI; * Audio maybe supported and played back internally or via an {@link AudioSink} implementation. *

*

- * Audio and video streams can be selected or muted via {@link #initStream(Uri, int, int, int)} + * Audio and video streams can be selected or muted via {@link #playStream(Uri, int, int, int)} * using the appropriate stream id's. *

*

@@ -56,7 +57,7 @@ import com.jogamp.opengl.util.TimeFrameI; *

* Most of the stream processing is performed on the decoding thread, a.k.a. StreamWorker: *

@@ -82,16 +83,17 @@ import com.jogamp.opengl.util.TimeFrameI; *

* * - * - * - * + * + * * + * + * * - * - * + * + * * - * - * + * + * *
Action {@link State} Before {@link State} After {@link GLMediaEventListener Event}
{@link #initStream(Uri, int, int, int)} {@link State#Uninitialized Uninitialized} {@link State#Initialized Initialized}1, {@link State#Uninitialized Uninitialized} {@link GLMediaEventListener#EVENT_CHANGE_INIT EVENT_CHANGE_INIT} or ( {@link GLMediaEventListener#EVENT_CHANGE_ERR EVENT_CHANGE_ERR} + {@link GLMediaEventListener#EVENT_CHANGE_UNINIT EVENT_CHANGE_UNINIT} )
{@link #initGL(GL)} {@link State#Initialized Initialized} {@link State#Paused Paused}, , {@link State#Uninitialized Uninitialized} {@link GLMediaEventListener#EVENT_CHANGE_PAUSE EVENT_CHANGE_PAUSE} or ( {@link GLMediaEventListener#EVENT_CHANGE_ERR EVENT_CHANGE_ERR} + {@link GLMediaEventListener#EVENT_CHANGE_UNINIT EVENT_CHANGE_UNINIT} )
{@link #play()} {@link State#Paused Paused} {@link State#Playing Playing} {@link GLMediaEventListener#EVENT_CHANGE_PLAY EVENT_CHANGE_PLAY}
{@link #playStream(Uri, int, int, int)} {@link State#Uninitialized Uninitialized} {@link State#Initialized Initialized}1, {@link State#Uninitialized Uninitialized} {@link GLMediaEventListener#EVENT_CHANGE_INIT EVENT_CHANGE_INIT} or ( {@link GLMediaEventListener#EVENT_CHANGE_ERR EVENT_CHANGE_ERR} + {@link GLMediaEventListener#EVENT_CHANGE_UNINIT EVENT_CHANGE_UNINIT} )
{@link #initGL(GL)} {@link State#Initialized Initialized}, {@link State#Uninitialized Uninitialized} {@link State#Playing Playing}, {@link State#Uninitialized Uninitialized} {@link GLMediaEventListener#EVENT_CHANGE_PLAY EVENT_CHANGE_PLAY} or ( {@link GLMediaEventListener#EVENT_CHANGE_ERR EVENT_CHANGE_ERR} + {@link GLMediaEventListener#EVENT_CHANGE_UNINIT EVENT_CHANGE_UNINIT} )
{@link #pause(boolean)} {@link State#Playing Playing} {@link State#Paused Paused} {@link GLMediaEventListener#EVENT_CHANGE_PAUSE EVENT_CHANGE_PAUSE}
{@link #resume()} {@link State#Paused Paused} {@link State#Playing Playing} {@link GLMediaEventListener#EVENT_CHANGE_PLAY EVENT_CHANGE_PLAY}
{@link #stop()} {@link State#Playing Playing}, {@link State#Paused Paused} {@link State#Uninitialized Uninitialized} {@link GLMediaEventListener#EVENT_CHANGE_PAUSE EVENT_CHANGE_PAUSE}
{@link #seek(int)} {@link State#Paused Paused}, {@link State#Playing Playing} {@link State#Paused Paused}, {@link State#Playing Playing} none
{@link #getNextTexture(GL)} {@link State#Paused Paused}, {@link State#Playing Playing} {@link State#Paused Paused}, {@link State#Playing Playing} none
{@link #getLastTexture()} {@link State#Paused Paused}, {@link State#Playing Playing} {@link State#Paused Paused}, {@link State#Playing Playing} none
{@link #getNextTexture(GL)} any same none
{@link #getLastTexture()} any same none
{@link TextureFrame#END_OF_STREAM_PTS END_OF_STREAM} {@link State#Playing Playing} {@link State#Paused Paused} {@link GLMediaEventListener#EVENT_CHANGE_EOS EVENT_CHANGE_EOS} + {@link GLMediaEventListener#EVENT_CHANGE_PAUSE EVENT_CHANGE_PAUSE}
{@link StreamException} ANY {@link State#Paused Paused}, {@link State#Uninitialized Uninitialized} {@link GLMediaEventListener#EVENT_CHANGE_ERR EVENT_CHANGE_ERR} + ( {@link GLMediaEventListener#EVENT_CHANGE_PAUSE EVENT_CHANGE_PAUSE} or {@link GLMediaEventListener#EVENT_CHANGE_UNINIT EVENT_CHANGE_UNINIT} )
{@link #destroy(GL)} ANY {@link State#Uninitialized Uninitialized} {@link GLMediaEventListener#EVENT_CHANGE_UNINIT EVENT_CHANGE_UNINIT}
{@link StreamException} any {@link State#Paused Paused}, {@link State#Uninitialized Uninitialized} {@link GLMediaEventListener#EVENT_CHANGE_ERR EVENT_CHANGE_ERR} + ( {@link GLMediaEventListener#EVENT_CHANGE_PAUSE EVENT_CHANGE_PAUSE} or {@link GLMediaEventListener#EVENT_CHANGE_UNINIT EVENT_CHANGE_UNINIT} )
{@link #destroy(GL)} any {@link State#Uninitialized Uninitialized} {@link GLMediaEventListener#EVENT_CHANGE_UNINIT EVENT_CHANGE_UNINIT}
*

* @@ -188,6 +190,7 @@ import com.jogamp.opengl.util.TimeFrameI; */ public interface GLMediaPlayer extends TextureSequence { public static final boolean DEBUG = Debug.debug("GLMediaPlayer"); + public static final boolean DEBUG_AVSYNC = Debug.debug("GLMediaPlayer.AVSync"); public static final boolean DEBUG_NATIVE = Debug.debug("GLMediaPlayer.Native"); /** Default texture count, value {@value}. */ @@ -372,7 +375,7 @@ public interface GLMediaPlayer extends TextureSequence { * @throws IllegalArgumentException if arguments are invalid * @since 2.3.0 */ - public void initStream(Uri streamLoc, int vid, int aid, int textureCount) throws IllegalStateException, IllegalArgumentException; + public void playStream(Uri streamLoc, int vid, int aid, int textureCount) throws IllegalStateException, IllegalArgumentException; /** * Returns the {@link StreamException} caught in the decoder thread, or null if none occured. @@ -389,7 +392,7 @@ public interface GLMediaPlayer extends TextureSequence { *

* Lifecycle: {@link State#Initialized} -> {@link State#Paused} or {@link State#Initialized} *

- * Argument gl is ignored if video is muted, see {@link #initStream(Uri, int, int, int)}. + * Argument gl is ignored if video is muted, see {@link #playStream(Uri, int, int, int)}. * * @param gl current GL object. Maybe null, for audio only. * @throws IllegalStateException if not invoked in {@link State#Initialized}. @@ -401,7 +404,7 @@ public interface GLMediaPlayer extends TextureSequence { /** * If implementation uses a {@link AudioSink}, it's instance will be returned. *

- * The {@link AudioSink} instance is available after {@link #initStream(Uri, int, int, int)}, + * The {@link AudioSink} instance is available after {@link #playStream(Uri, int, int, int)}, * if used by implementation. *

*/ @@ -415,6 +418,14 @@ public interface GLMediaPlayer extends TextureSequence { */ public State destroy(GL gl); + /** + * Stops streaming and releases the GL, stream and other resources, but keeps {@link #attachObject(String, Object) attached user objects}. + *

+ * Lifecycle: ANY -> {@link State#Uninitialized} + *

+ */ + public State stop(); + /** * Sets the playback speed. *

@@ -452,7 +463,7 @@ public interface GLMediaPlayer extends TextureSequence { * Lifecycle: {@link State#Paused} -> {@link State#Playing} *

*/ - public State play(); + public State resume(); /** * Pauses the StreamWorker decoding thread. @@ -460,7 +471,7 @@ public interface GLMediaPlayer extends TextureSequence { * Lifecycle: {@link State#Playing} -> {@link State#Paused} *

*

- * If a new frame is desired after the next {@link #play()} call, + * If a new frame is desired after the next {@link #resume()} call, * e.g. to make a snapshot of a camera input stream, * flush shall be set to true. *

@@ -498,13 +509,13 @@ public interface GLMediaPlayer extends TextureSequence { public int getAID(); /** - * @return the current decoded frame count since {@link #play()} and {@link #seek(int)} + * @return the current decoded frame count since {@link #resume()} and {@link #seek(int)} * as increased by {@link #getNextTexture(GL)} or the decoding thread. */ public int getDecodedFrameCount(); /** - * @return the current presented frame count since {@link #play()} and {@link #seek(int)} + * @return the current presented frame count since {@link #resume()} and {@link #seek(int)} * as increased by {@link #getNextTexture(GL)} for new frames. */ public int getPresentedFrameCount(); @@ -547,7 +558,7 @@ public interface GLMediaPlayer extends TextureSequence { public TextureSequence.TextureFrame getNextTexture(GL gl) throws IllegalStateException; /** - * Return the stream location, as set by {@link #initStream(Uri, int, int, int)}. + * Return the stream location, as set by {@link #playStream(Uri, int, int, int)}. * @since 2.3.0 */ public Uri getUri(); -- cgit v1.2.3