aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl
diff options
context:
space:
mode:
authorSven Göthel <[email protected]>2024-01-31 11:28:10 +0100
committerSven Göthel <[email protected]>2024-01-31 11:28:10 +0100
commitb8b692e9cf3120d788ae912514f54948ddccacf5 (patch)
treeaafde7897934d548789297efc20336754af06624 /src/jogl
parent72065d9e2a9d6480c34afc9920071d5ed577d37a (diff)
GLMediaPlayer: Split GLMediaFrameListener (rarely used) from GLMediaEventListener, easing listener callbacks; Prepare SubtitleEventListener generalization (Bug 1494)
Moves pushSound(), pushSubtitle*() from FFMPEGMediaPlayer to GLMediaPlayerImpl, as it is handled in a generic way - even though currently only called by native FFMPEGMediaPlayer implementation. Note: This patch is incomplete, i.e. not even compile clean. But choses as-is to semantically split the work to ease review.
Diffstat (limited to 'src/jogl')
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java39
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java121
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java21
-rw-r--r--src/jogl/native/libav/ffmpeg_static.c9
-rw-r--r--src/jogl/native/libav/ffmpeg_static.h1
5 files changed, 136 insertions, 55 deletions
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 91211df58..987031b6b 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java
@@ -291,17 +291,14 @@ public interface GLMediaPlayer extends TextureSequence {
}
/**
- * {@inheritDoc}
- * <p>
- * As the contract of {@link TexSeqEventListener} requests,
- * implementations of {@link GLMediaEventListener} shall also:
+ * As the contract of {@link GLMediaFrameListener} and {@link TexSeqEventListener} requests,
+ * implementations of {@link GLMediaEventListener} shall:
* <ul>
* <li>off-load complex or {@link GLMediaPlayer} commands on another thread, or</li>
* <li>simply changing a volatile state of their {@link GLEventListener} implementation.</li>
* </ul>
- * </p>
*/
- public interface GLMediaEventListener extends TexSeqEventListener<GLMediaPlayer> {
+ public interface GLMediaEventListener {
/**
* @param mp the event source
* @param event_mask the changes attributes
@@ -309,6 +306,19 @@ public interface GLMediaPlayer extends TextureSequence {
*/
public void attributesChanged(GLMediaPlayer mp, EventMask event_mask, long when);
}
+ /**
+ * {@inheritDoc}
+ * <p>
+ * As the contract of {@link TexSeqEventListener} requests,
+ * implementations of {@link GLMediaEventListener} shall also:
+ * <ul>
+ * <li>off-load complex or {@link GLMediaPlayer} commands on another thread, or</li>
+ * <li>simply changing a volatile state of their {@link GLEventListener} implementation.</li>
+ * </ul>
+ * </p>
+ */
+ public interface GLMediaFrameListener extends TexSeqEventListener<GLMediaPlayer> {
+ }
/** Changes attributes event mask */
public static final class EventMask {
@@ -905,10 +915,19 @@ public interface GLMediaPlayer extends TextureSequence {
/** Return all {@link GLMediaEventListener} of this player. */
public GLMediaEventListener[] getEventListeners();
- /** Sets the {@link ASSEventListener} for this player. */
- public void setASSEventListener(ASSEventListener l);
- /** Returns the {@link #setASSEventListener(ASSEventListener)} of this player. */
- public ASSEventListener getASSEventListener();
+ /** Adds a {@link GLMediaFrameListener} to this player. */
+ public void addFrameListener(GLMediaFrameListener l);
+
+ /** Removes a {@link GLMediaFrameListener} to this player. */
+ public void removeFrameListener(GLMediaFrameListener l);
+
+ /** Return all {@link GLMediaFrameListener} of this player. */
+ public GLMediaFrameListener[] getFrameListeners();
+
+ /** Sets the {@link SubtitleEventListener} for this player. */
+ public void setSubtitleEventListener(SubtitleEventListener l);
+ /** Returns the {@link #setSubtitleEventListener(SubtitleEventListener)} of this player. */
+ public SubtitleEventListener getSubtitleEventListener();
/**
* Returns the attached user object for the given name.
diff --git a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java
index a963f935b..ed03278b9 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java
@@ -34,7 +34,6 @@ import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.Map;
import com.jogamp.nativewindow.AbstractGraphicsDevice;
@@ -66,8 +65,12 @@ import com.jogamp.common.util.TSPrinter;
import com.jogamp.common.util.WorkerThread;
import com.jogamp.math.FloatUtil;
import com.jogamp.opengl.GLExtensions;
-import com.jogamp.opengl.util.av.ASSEventListener;
+import com.jogamp.opengl.util.av.SubtitleEventListener;
import com.jogamp.opengl.util.av.GLMediaPlayer;
+import com.jogamp.opengl.util.av.SubASSEventLine;
+import com.jogamp.opengl.util.av.SubEmptyEvent;
+import com.jogamp.opengl.util.av.SubTextureEvent;
+import com.jogamp.opengl.util.av.SubtitleEvent;
import com.jogamp.opengl.util.glsl.ShaderCode;
import com.jogamp.opengl.util.texture.Texture;
import com.jogamp.opengl.util.texture.TextureData;
@@ -199,7 +202,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
protected AudioSink audioSink = null;
protected boolean audioSinkPlaySpeedSet = false;
- protected volatile ASSEventListener assEventListener = null;
+ protected volatile SubtitleEventListener subEventListener = null;
/** AV System Clock Reference (SCR) */
private final PTS av_scr = new PTS( () -> { return State.Playing == state ? playSpeed : 0f; } );
@@ -238,7 +241,8 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
*/
private boolean isInGLOrientation = false;
- private final ArrayList<GLMediaEventListener> eventListeners = new ArrayList<GLMediaEventListener>();
+ private final ArrayList<GLMediaEventListener> eventListener = new ArrayList<GLMediaEventListener>();
+ private final ArrayList<GLMediaFrameListener> frameListener = new ArrayList<GLMediaFrameListener>();
protected GLMediaPlayerImpl() {
this.textureCount=0;
@@ -813,7 +817,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
} else {
videoFramesFree = new LFRingbuffer<TextureFrame>(videoFramesOrig);
videoFramesDecoded = new LFRingbuffer<TextureFrame>(TextureFrame[].class, textureCount);
- lastFrame = videoFramesFree.getBlocking( );
+ lastFrame = videoFramesFree.getBlocking();
}
} else {
videoFramesOrig = null;
@@ -1428,9 +1432,10 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
if( 0 == frame.getDuration() ) { // patch frame duration if not set already
frame.setDuration( (int) frame_duration );
}
- synchronized(eventListenersLock) {
- for(final Iterator<GLMediaEventListener> i = eventListeners.iterator(); i.hasNext(); ) {
- i.next().newFrameAvailable(this, frame, currentMillis);
+ synchronized(frameListenerLock) {
+ final int sz = frameListener.size();
+ for(int i=0; i<sz; ++i) {
+ frameListener.get(i).newFrameAvailable(this, frame, currentMillis);
}
}
}
@@ -1649,6 +1654,51 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
private static DefaultGraphicsDevice singleOwner = null;
private static int singleCount = 0;
+ protected final void pushSound(final ByteBuffer sampleData, final int data_size, final int audio_pts) {
+ if( audioStreamEnabled() ) {
+ audioSink.enqueueData( audio_pts, sampleData, data_size);
+ }
+ }
+ protected final void pushSubtitleEmpty(final int start_display_pts, final int end_display_pts) {
+ if( null != subEventListener ) {
+ subEventListener.run( new SubEmptyEvent(start_display_pts, end_display_pts) );
+ }
+ }
+ protected final void pushSubtitleText(final String text, final int start_display_pts, final int end_display_pts) {
+ if( null != subEventListener ) {
+ subEventListener.run( new SubASSEventLine(SubtitleEvent.Format.ASS_TEXT, text, start_display_pts, end_display_pts) );
+ }
+ }
+ protected final void pushSubtitleASS(final String ass, final int start_display_pts, final int end_display_pts) {
+ if( null != subEventListener ) {
+ subEventListener.run( new SubASSEventLine(SubtitleEvent.Format.ASS_FFMPEG, ass, start_display_pts, end_display_pts) );
+ }
+ }
+ private final SubTextureEvent.TextureOwner subTexRelease = new SubTextureEvent.TextureOwner() {
+ @Override
+ public void release(final Texture tex) {
+ if( null != subTexFree && null != tex ) { // put back
+ subTexFree.put(tex);
+ }
+ }
+
+ };
+ protected final void pushSubtitleTex(final Object texObj, final int texID, final int texWidth, final int texHeight,
+ final int x, final int y, final int width, final int height,
+ final int start_display_pts, final int end_display_pts)
+ {
+ if( null != subEventListener ) {
+ final Texture tex = (Texture)texObj;
+ if( null != tex ) {
+ tex.set(texWidth, texHeight, width, height);
+ }
+ subEventListener.run( new SubTextureEvent(new Vec2i(x, y), new Vec2i(width, height), tex,
+ start_display_pts, end_display_pts, subTexRelease) );
+ } else {
+ subTexRelease.release((Texture)texObj); // release right away
+ }
+ }
+
protected final GLMediaPlayer.EventMask addStateEventMask(final GLMediaPlayer.EventMask eventMask, final State newState) {
if( state != newState ) {
switch( newState ) {
@@ -1675,9 +1725,10 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
if( DEBUG ) {
logout.println("GLMediaPlayer.AttributesChanged: "+eventMask+", state "+state+", when "+now);
}
- synchronized(eventListenersLock) {
- for(final Iterator<GLMediaEventListener> i = eventListeners.iterator(); i.hasNext(); ) {
- i.next().attributesChanged(this, eventMask, now);
+ synchronized(eventListenerLock) {
+ final int sz = eventListener.size();
+ for(int i=0; i<sz; ++i) {
+ eventListener.get(i).attributesChanged(this, eventMask, now);
}
}
}
@@ -2060,8 +2111,8 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
if(l == null) {
return;
}
- synchronized(eventListenersLock) {
- eventListeners.add(l);
+ synchronized(eventListenerLock) {
+ eventListener.add(l);
}
}
@@ -2070,25 +2121,53 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
if (l == null) {
return;
}
- synchronized(eventListenersLock) {
- eventListeners.remove(l);
+ synchronized(eventListenerLock) {
+ eventListener.remove(l);
}
}
@Override
public final GLMediaEventListener[] getEventListeners() {
- synchronized(eventListenersLock) {
- return eventListeners.toArray(new GLMediaEventListener[eventListeners.size()]);
+ synchronized(eventListenerLock) {
+ return eventListener.toArray(new GLMediaEventListener[eventListener.size()]);
+ }
+ }
+ private final Object eventListenerLock = new Object();
+
+ @Override
+ public final void addFrameListener(final GLMediaFrameListener l) {
+ if(l == null) {
+ return;
+ }
+ synchronized(frameListenerLock) {
+ frameListener.add(l);
+ }
+ }
+
+ @Override
+ public final void removeFrameListener(final GLMediaFrameListener l) {
+ if (l == null) {
+ return;
+ }
+ synchronized(frameListenerLock) {
+ frameListener.remove(l);
+ }
+ }
+
+ @Override
+ public final GLMediaFrameListener[] getFrameListeners() {
+ synchronized(frameListenerLock) {
+ return frameListener.toArray(new GLMediaFrameListener[frameListener.size()]);
}
}
- private final Object eventListenersLock = new Object();
+ private final Object frameListenerLock = new Object();
@Override
- public final void setASSEventListener(final ASSEventListener l) {
- this.assEventListener = l;
+ public final void setSubtitleEventListener(final SubtitleEventListener l) {
+ this.subEventListener = l;
}
@Override
- public final ASSEventListener getASSEventListener() { return assEventListener; }
+ public final SubtitleEventListener getSubtitleEventListener() { return subEventListener; }
@Override
public final Object getAttachedObject(final String name) {
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java
index 2e48b49e6..e6784273e 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java
@@ -1006,26 +1006,5 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
}
return vPTS;
}
-
- final void pushSound(final ByteBuffer sampleData, final int data_size, final int audio_pts) {
- if( audioStreamEnabled() ) {
- audioSink.enqueueData( audio_pts, sampleData, data_size);
- }
- }
- final void pushSubtitleText(final String text, final int pts, final int start_display_pts, final int end_display_pts) {
- if( null != assEventListener ) {
- if( start_display_pts > getPTS().get(Clock.currentMillis()) ) {
- assEventListener.run( new ASSEventLine(ASSEventLine.Format.TEXT, text, start_display_pts, end_display_pts) );
- }
- }
- }
- final void pushSubtitleASS(final String ass, final int pts, final int start_display_pts, final int end_display_pts) {
- if( null != assEventListener ) {
- assEventListener.run( new ASSEventLine(ASSEventLine.Format.FFMPEG, ass, start_display_pts, end_display_pts) );
- }
- }
- final void pushSubtitleTex(final int texID, final int x, final int y, final int width, final int height, final int pts, final int start_display_pts, final int end_display_pts) {
- // System.err.println("SubTex["+texID+"]: "+x+"/"+y+" "+width+"x"+height+", pts "+pts+" ["+start_display_pts+".."+end_display_pts+"] "+(end_display_pts-start_display_pts+1));
- }
}
diff --git a/src/jogl/native/libav/ffmpeg_static.c b/src/jogl/native/libav/ffmpeg_static.c
index a0145cee8..a8db0652c 100644
--- a/src/jogl/native/libav/ffmpeg_static.c
+++ b/src/jogl/native/libav/ffmpeg_static.c
@@ -39,6 +39,7 @@ jmethodID ffmpeg_jni_mid_pushSound = NULL;
jmethodID ffmpeg_jni_mid_pushSubtitleText = NULL;
jmethodID ffmpeg_jni_mid_pushSubtitleASS = NULL;
jmethodID ffmpeg_jni_mid_pushSubtitleTex = NULL;
+jmethodID ffmpeg_jni_mid_pushSubtitleEmpty = NULL;
jmethodID ffmpeg_jni_mid_updateAttributes = NULL;
jmethodID ffmpeg_jni_mid_setIsGLOriented = NULL;
jmethodID ffmpeg_jni_mid_setupFFAttributes = NULL;
@@ -68,9 +69,10 @@ JNIEXPORT jboolean JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGStaticNatives_i
}
ffmpeg_jni_mid_pushSound = (*env)->GetMethodID(env, ffmpegMediaPlayerClazz, "pushSound", "(Ljava/nio/ByteBuffer;II)V");
- ffmpeg_jni_mid_pushSubtitleText = (*env)->GetMethodID(env, ffmpegMediaPlayerClazz, "pushSubtitleText", "(Ljava/lang/String;III)V");
- ffmpeg_jni_mid_pushSubtitleASS = (*env)->GetMethodID(env, ffmpegMediaPlayerClazz, "pushSubtitleASS", "(Ljava/lang/String;III)V");
- ffmpeg_jni_mid_pushSubtitleTex = (*env)->GetMethodID(env, ffmpegMediaPlayerClazz, "pushSubtitleTex", "(IIIIIIII)V");
+ ffmpeg_jni_mid_pushSubtitleText = (*env)->GetMethodID(env, ffmpegMediaPlayerClazz, "pushSubtitleText", "(Ljava/lang/String;II)V");
+ ffmpeg_jni_mid_pushSubtitleASS = (*env)->GetMethodID(env, ffmpegMediaPlayerClazz, "pushSubtitleASS", "(Ljava/lang/String;II)V");
+ ffmpeg_jni_mid_pushSubtitleTex = (*env)->GetMethodID(env, ffmpegMediaPlayerClazz, "pushSubtitleTex", "(Ljava/lang/Object;IIIIIIIII)V");
+ ffmpeg_jni_mid_pushSubtitleEmpty = (*env)->GetMethodID(env, ffmpegMediaPlayerClazz, "pushSubtitleEmpty", "(II)V");
ffmpeg_jni_mid_updateAttributes = (*env)->GetMethodID(env, ffmpegMediaPlayerClazz, "updateAttributes",
"(Ljava/lang/String;[I[Ljava/lang/String;I[I[Ljava/lang/String;I[I[Ljava/lang/String;IIIIIIFIIILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
ffmpeg_jni_mid_setIsGLOriented = (*env)->GetMethodID(env, ffmpegMediaPlayerClazz, "setIsGLOriented", "(Z)V");
@@ -81,6 +83,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGStaticNatives_i
ffmpeg_jni_mid_pushSubtitleText == NULL ||
ffmpeg_jni_mid_pushSubtitleASS == NULL ||
ffmpeg_jni_mid_pushSubtitleTex == NULL ||
+ ffmpeg_jni_mid_pushSubtitleEmpty == NULL ||
ffmpeg_jni_mid_updateAttributes == NULL ||
ffmpeg_jni_mid_setIsGLOriented == NULL ||
ffmpeg_jni_mid_setupFFAttributes == NULL ||
diff --git a/src/jogl/native/libav/ffmpeg_static.h b/src/jogl/native/libav/ffmpeg_static.h
index 4bdb1ff55..3fb6c2ca5 100644
--- a/src/jogl/native/libav/ffmpeg_static.h
+++ b/src/jogl/native/libav/ffmpeg_static.h
@@ -44,6 +44,7 @@ extern jmethodID ffmpeg_jni_mid_pushSound;
extern jmethodID ffmpeg_jni_mid_pushSubtitleText;
extern jmethodID ffmpeg_jni_mid_pushSubtitleASS;
extern jmethodID ffmpeg_jni_mid_pushSubtitleTex;
+extern jmethodID ffmpeg_jni_mid_pushSubtitleEmpty;
extern jmethodID ffmpeg_jni_mid_updateAttributes;
extern jmethodID ffmpeg_jni_mid_setIsGLOriented;
extern jmethodID ffmpeg_jni_mid_setupFFAttributes;