diff options
author | Sven Gothel <[email protected]> | 2014-02-22 08:05:42 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-02-22 08:05:42 +0100 |
commit | c67de337a8aaf52e36104c3f13e273aa19d21f1f (patch) | |
tree | 13c16301a9414597bca3f5ecbf49319016f2d0b8 | |
parent | c4368e89c0fc3ee4de659cd760bc812092bba054 (diff) |
Bug 927 - Multithreading (MT) - GLMediaPlayer.GLMediaEventListener: Remind that commands shall be off-loaded on another thread!
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; } |