aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2014-02-22 08:05:42 +0100
committerSven Gothel <[email protected]>2014-02-22 08:05:42 +0100
commitc67de337a8aaf52e36104c3f13e273aa19d21f1f (patch)
tree13c16301a9414597bca3f5ecbf49319016f2d0b8
parentc4368e89c0fc3ee4de659cd760bc812092bba054 (diff)
Bug 927 - Multithreading (MT) - GLMediaPlayer.GLMediaEventListener: Remind that commands shall be off-loaded on another thread!
-rw-r--r--make/scripts/tests.sh8
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java8
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java12
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/CrossFadePlayer.java85
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java9
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java43
6 files changed, 96 insertions, 69 deletions
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index f6e3ab244..4381f5780 100644
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -64,7 +64,8 @@ fi
#export INTEL_STRICT_CONFORMANCE=1
# export ALSOFT_LOGLEVEL=[0..4]
-export ALSOFT_LOGLEVEL=3
+# export ALSOFT_LOGLEVEL=3
+# export ALSOFT_LOGLEVEL=3
#export ALSOFT_TRAP_ERROR=true
#export ALSOFT_TRAP_AL_ERROR=true
#export ALSOFT_TRAP_ALC_ERROR=true
@@ -244,7 +245,7 @@ function jrun() {
#D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.GLJPanel -Djogl.debug.TileRenderer -Djogl.debug.TileRenderer.PNG"
#D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.GLJPanel -Djogl.debug.TileRenderer"
#D_ARGS="-Djogl.debug.PNG -Dnewt.debug.Display.PointerIcon"
- #D_ARGS="-Djogl.debug.JPEGImage"
+ #D_ARGS="-Djogl.debug.JPEGImage -Djogamp.debug.Bitstream"
#D_ARGS="-Djogl.debug.GLDrawable -Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.CapabilitiesChooser"
#X_ARGS="-Dsun.java2d.noddraw=True -Dsun.java2d.opengl=True -Dsun.java2d.xrender=false"
#X_ARGS="-Dsun.java2d.noddraw=True -Dsun.java2d.opengl=false -Dsun.java2d.xrender=false"
@@ -368,7 +369,8 @@ function testawtswt() {
#
#testnoawt jogamp.opengl.openal.av.ALDummyUsage $*
#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube $*
-testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple $*
+testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.CrossFadePlayer $*
#
# performance tests
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 9957f2093..5a455c8bd 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java
@@ -30,6 +30,7 @@ package com.jogamp.opengl.util.av;
import java.net.URI;
import javax.media.opengl.GL;
+import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLException;
import jogamp.opengl.Debug;
@@ -255,7 +256,12 @@ public interface GLMediaPlayer extends TextureSequence {
/**
* {@inheritDoc}
* <p>
- * See {@link TexSeqEventListener} for semantics and usage.
+ * 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 GLMediaEventListener extends TexSeqEventListener<GLMediaPlayer> {
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java
index 6c2949c2b..ab9d1f8f0 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java
@@ -31,6 +31,7 @@ import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLRunnable;
import javax.media.opengl.GLEventListener;
+
import com.jogamp.opengl.util.TimeFrameI;
/**
@@ -133,17 +134,16 @@ public interface TextureSequence {
/**
* Event listener to notify users of updates regarding the {@link TextureSequence}.
* <p>
- * The implementation sending the events, and hence calling down to all listeners,
- * does not necessarily make the user's OpenGL context current.
+ * Implementations sending events down to all listeners,
+ * while not necessarily making the user's OpenGL context current.
* </p>
* <p>
- * Further more, the call may happen off-thread, possibly holding another, possibly shared, OpenGL context current.
- * </p>
+ * Events may be sent from a 3rd-party thread, possibly holding another, maybe shared, OpenGL context current.<br/>
* Hence a user shall not issue <i>any</i> OpenGL, time consuming
- * or {@link TextureSequence} lifecycle operations directly.<br>
+ * or {@link TextureSequence} operations directly.<br>
* Instead, the user shall:
* <ul>
- * <li>issue commands off-thread via spawning off another thread, or</li>
+ * <li>off-load complex or {@link TextureSequence} commands on another thread, or</li>
* <li>injecting {@link GLRunnable} objects via {@link GLAutoDrawable#invoke(boolean, GLRunnable)}, or</li>
* <li>simply changing a volatile state of their {@link GLEventListener} implementation.</li>
* </ul>
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/CrossFadePlayer.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/CrossFadePlayer.java
index c656663ee..02f62c415 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/CrossFadePlayer.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/CrossFadePlayer.java
@@ -35,10 +35,6 @@ import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException;
import com.jogamp.opengl.util.av.GLMediaPlayerFactory;
import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
-import javax.media.opengl.GLAutoDrawable;
-import javax.media.opengl.GLEventListener;
-import javax.media.opengl.GLException;
-
import java.io.File;
import java.net.URI;
@@ -48,7 +44,7 @@ import java.net.URI;
*/
public class CrossFadePlayer
{
- static GLMediaPlayer[] player;
+ static GLMediaPlayer[] player;
static volatile boolean stop = false;
public static void main(String[] args)
@@ -63,13 +59,11 @@ public class CrossFadePlayer
GLMediaEventListener mediaEventListener = new GLMediaEventListener()
{
-
@Override
- public void newFrameAvailable(GLMediaPlayer ts, TextureFrame newFrame,
- long when) { }
+ public void newFrameAvailable(GLMediaPlayer ts, TextureFrame newFrame, long when) { }
@Override
- public void attributesChanged(GLMediaPlayer mp, int event_mask, long when)
+ public void attributesChanged(final GLMediaPlayer mp, int event_mask, long when)
{
System.out.println("\n***\nEvent mask changed: " + event_mask);
System.out.println("Timestamp: "+ when);
@@ -78,32 +72,41 @@ public class CrossFadePlayer
if ((event_mask & GLMediaEventListener.EVENT_CHANGE_INIT) !=0) {
System.out.println("Duration: " + mp.getDuration() + "ms");
System.out.println("Volume: " + mp.getAudioVolume());
- try {
- System.out.println("player.initGL()...");
- mp.initGL(null);
- }
- catch (IllegalStateException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- catch (GLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- catch (StreamException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }else if ((event_mask & GLMediaEventListener.EVENT_CHANGE_PAUSE) !=0) {
- System.out.println("player.play()...");
- System.out.println("mp.setPlaySpeed(1f) returned: " + mp.setPlaySpeed(1f));
- mp.seek(0);
- mp.play();
- }else if ((event_mask & GLMediaEventListener.EVENT_CHANGE_PLAY) !=0) {
+ System.out.println("player.initGL()...");
+ new Thread() {
+ public void run() {
+ try {
+ mp.initGL(null);
+ if ( GLMediaPlayer.State.Paused == mp.getState() ) { // init OK
+ mp.play();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }.start();
+ } else if ((event_mask & GLMediaEventListener.EVENT_CHANGE_PAUSE) !=0) {
+ System.out.println("player.paused()...");
+ } else if ((event_mask & GLMediaEventListener.EVENT_CHANGE_PLAY) !=0) {
System.out.println("playing...");
System.out.println(mp.toString());
System.out.println(mp.getAudioSink().toString());
- }
+ } else if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) {
+ final StreamException se = mp.getStreamException();
+ if( null != se ) {
+ System.err.println("Player State: EOS + Exception");
+ stop = true;
+ } else {
+ System.err.println("Player State: EOS");
+ new Thread() {
+ public void run() {
+ System.out.println("mp.setPlaySpeed(1f) returned: " + mp.setPlaySpeed(1f));
+ mp.seek(0);
+ mp.play();
+ }
+ }.start();
+ }
+ }
if( 0 != ( ( GLMediaEventListener.EVENT_CHANGE_ERR | GLMediaEventListener.EVENT_CHANGE_EOS ) & event_mask ) ) {
final StreamException se = mp.getStreamException();
if( null != se ) {
@@ -111,7 +114,7 @@ public class CrossFadePlayer
}
new Thread() {
public void run() {
- System.out.println("terminating...");
+ System.out.println("terminating...");
stop = true;
}
}.start();
@@ -123,13 +126,13 @@ public class CrossFadePlayer
// Initialize media players
player = new GLMediaPlayer[args.length];
int i=0;
- for( String arg: args) {
+ for( String arg: args ) {
player[i] = GLMediaPlayerFactory.createDefault();
if(player[i]!=null){
System.out.println("Created CrossFade player: "+ i + " " + player[i].getClass().getName());
player[i].addEventListener(mediaEventListener);
try {
- String filename = args[i];
+ final String filename = arg;
if(filename.equals("")){
System.out.println("No file selected: arg " + i +" = "+ filename);
player[i]=null;
@@ -157,7 +160,7 @@ public class CrossFadePlayer
// Main thread CrossFade until playback is done
long startTime = com.jogamp.common.os.Platform.currentTimeMillis();
- double piPlayers = Math.PI*2.0f/(double)args.length;
+ double piPlayers = Math.PI*2.0f/args.length;
StreamException se = null;
while( null == se && stop == false ) {
try {
@@ -173,18 +176,18 @@ public class CrossFadePlayer
}
}
}
-
+
// tune the volume on players to crossfade!
- float progress = (float)(com.jogamp.common.os.Platform.currentTimeMillis()-startTime)/maxDuration;
+ float progress = (com.jogamp.common.os.Platform.currentTimeMillis()-startTime)/maxDuration;
i = 0;
for(GLMediaPlayer p: player){
if(p!=null){
AudioSink sink = p.getAudioSink();
if(sink != null){
- float volume = (float) (0.5f+(0.5f*(Math.cos(40.0f*progress+(piPlayers*(float)i)))));
- float playbacktime = (float)(com.jogamp.common.os.Platform.currentTimeMillis()-startTime);
- System.out.println("player: "+ i +" volume = " + volume +" progress = "+ progress +" time = "+ playbacktime + " / duration = " + maxDuration);
+ float volume = (float) (0.5f+(0.5f*(Math.cos(40.0f*progress+(piPlayers*i)))));
+ float playbacktime = com.jogamp.common.os.Platform.currentTimeMillis()-startTime;
+ // System.out.println("player: "+ i +" volume = " + volume +" progress = "+ progress +" time = "+ playbacktime + " / duration = " + maxDuration);
sink.setVolume(volume);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java
index daa09c3b1..b148ebabd 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java
@@ -112,9 +112,12 @@ public class MovieCube implements GLEventListener {
resetGLState();
}
if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) {
- // loop for-ever ..
- mPlayer.seek(0);
- mPlayer.play();
+ new Thread() {
+ public void run() {
+ // loop for-ever ..
+ mPlayer.seek(0);
+ mPlayer.play();
+ } }.start();
}
}
});
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java
index e609dde55..787dbab78 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java
@@ -321,9 +321,12 @@ public class MovieSimple implements GLEventListener {
resetGLState();
}
if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) {
- // loop for-ever ..
- mPlayer.seek(0);
- mPlayer.play();
+ new Thread() {
+ public void run() {
+ // loop for-ever ..
+ mPlayer.seek(0);
+ mPlayer.play();
+ } }.start();
}
}
});
@@ -801,19 +804,24 @@ public class MovieSimple implements GLEventListener {
final GLAnimatorControl anim = window.getAnimator();
anim.setUpdateFPSFrames(60, null);
anim.resetFPSCounter();
-
/**
* Kick off player w/o GLEventListener, i.e. for audio only.
*
- try {
- ms.mPlayer.initGL(null);
- } catch (Exception e) {
- e.printStackTrace();
- destroyWindow();
- return;
- }
- ms.mPlayer.play();
- System.out.println("play.1 "+ms.mPlayer);
+ new Thread() {
+ public void run() {
+ try {
+ mp.initGL(null);
+ if ( GLMediaPlayer.State.Paused == mp.getState() ) { // init OK
+ mp.play();
+ }
+ System.out.println("play.1 "+mp);
+ } catch (Exception e) {
+ e.printStackTrace();
+ destroyWindow();
+ return;
+ }
+ }
+ }.start();
*/
}
if( 0 != ( GLMediaEventListener.EVENT_CHANGE_PLAY & event_mask ) ) {
@@ -831,8 +839,13 @@ public class MovieSimple implements GLEventListener {
} else {
System.err.println("MovieSimple State: EOS");
if( loopEOS ) {
- ms.mPlayer.seek(0);
- ms.mPlayer.play();
+ new Thread() {
+ public void run() {
+ mp.setPlaySpeed(1f);
+ mp.seek(0);
+ mp.play();
+ }
+ }.start();
} else {
destroy = true;
}