diff options
23 files changed, 820 insertions, 570 deletions
diff --git a/src/demos/com/jogamp/opengl/demos/android/MovieCubeActivity0a.java b/src/demos/com/jogamp/opengl/demos/android/MovieCubeActivity0a.java index cdbaa7872..dfd0c94dc 100644 --- a/src/demos/com/jogamp/opengl/demos/android/MovieCubeActivity0a.java +++ b/src/demos/com/jogamp/opengl/demos/android/MovieCubeActivity0a.java @@ -125,7 +125,7 @@ public class MovieCubeActivity0a extends NewtBaseActivity { } } }); - demoMain.initStream(streamLoc, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 0); + demoMain.playStream(streamLoc, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 0); } catch (final IOException e) { e.printStackTrace(); } diff --git a/src/demos/com/jogamp/opengl/demos/android/MovieCubeActivity0b.java b/src/demos/com/jogamp/opengl/demos/android/MovieCubeActivity0b.java index b04487b5f..649739e09 100644 --- a/src/demos/com/jogamp/opengl/demos/android/MovieCubeActivity0b.java +++ b/src/demos/com/jogamp/opengl/demos/android/MovieCubeActivity0b.java @@ -127,7 +127,7 @@ public class MovieCubeActivity0b extends NewtBaseActivity { } } }); - demoMain.initStream(streamLoc, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 0); + demoMain.playStream(streamLoc, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 0); } catch (final IOException e) { e.printStackTrace(); } diff --git a/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivity0.java b/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivity0.java index 07d0b9914..4b051a8cd 100644 --- a/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivity0.java +++ b/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivity0.java @@ -121,7 +121,7 @@ public class MovieSimpleActivity0 extends NewtBaseActivity { } } }); - demoMain.initStream(streamLoc, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 0); + demoMain.playStream(streamLoc, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 0); scrn.removeReference(); diff --git a/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivity1.java b/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivity1.java index d7a2aeae1..64a3c7c69 100644 --- a/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivity1.java +++ b/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivity1.java @@ -158,7 +158,7 @@ public class MovieSimpleActivity1 extends NewtBaseActivity { } } }); - demoMain.initStream(streamLoc0, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 0); + demoMain.playStream(streamLoc0, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 0); if(mPlayerHUD) { final GLMediaPlayer mPlayerShared = mPlayerSharedHUD ? mPlayerMain : null; @@ -205,7 +205,7 @@ public class MovieSimpleActivity1 extends NewtBaseActivity { } } }); - demoHUD.initStream(streamLoc1, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 0); + demoHUD.playStream(streamLoc1, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 0); glWindowHUD.setPosition(windowBounds.getX(), windowBounds.getY()); glWindowHUD.setSize(windowBounds.getWidth(), windowBounds.getHeight()); diff --git a/src/demos/com/jogamp/opengl/demos/av/CrossFadePlayer.java b/src/demos/com/jogamp/opengl/demos/av/CrossFadePlayer.java index a4d5e73de..0e028279c 100644 --- a/src/demos/com/jogamp/opengl/demos/av/CrossFadePlayer.java +++ b/src/demos/com/jogamp/opengl/demos/av/CrossFadePlayer.java @@ -79,7 +79,7 @@ public class CrossFadePlayer try {
mp.initGL(null);
if ( GLMediaPlayer.State.Paused == mp.getState() ) { // init OK
- mp.play();
+ mp.resume();
}
} catch (final Exception e) {
e.printStackTrace();
@@ -103,7 +103,7 @@ public class CrossFadePlayer public void run() {
System.out.println("mp.setPlaySpeed(1f) returned: " + mp.setPlaySpeed(1f));
mp.seek(0);
- mp.play();
+ mp.resume();
}
}.start();
}
@@ -145,7 +145,7 @@ public class CrossFadePlayer final Uri uri = Uri.valueOf(file);
System.out.println("State of player "+ i +": " + player[i].getState().toString());
System.out.println("...initializing stream "+ i +"...");
- player[i].initStream(uri, GLMediaPlayer.STREAM_ID_NONE, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.TEXTURE_COUNT_DEFAULT);
+ player[i].playStream(uri, GLMediaPlayer.STREAM_ID_NONE, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.TEXTURE_COUNT_DEFAULT);
}
}
diff --git a/src/demos/com/jogamp/opengl/demos/av/MovieCube.java b/src/demos/com/jogamp/opengl/demos/av/MovieCube.java index caf2f9381..33e04d05b 100644 --- a/src/demos/com/jogamp/opengl/demos/av/MovieCube.java +++ b/src/demos/com/jogamp/opengl/demos/av/MovieCube.java @@ -98,7 +98,7 @@ public class MovieCube implements GLEventListener { } /** - * Default constructor which also issues {@link #initStream(URI, int, int, int)} w/ default values + * Default constructor which also issues {@link #playStream(URI, int, int, int)} w/ default values * and polls until the {@link GLMediaPlayer} is {@link GLMediaPlayer.State#Initialized}. * If {@link GLMediaEventListener#EVENT_CHANGE_EOS} is reached, the stream is started over again. * <p> @@ -125,27 +125,16 @@ public class MovieCube implements GLEventListener { public void run() { // loop for-ever .. mPlayer.seek(0); - mPlayer.play(); + mPlayer.resume(); } }.start(); } } }); - initStream(defURI, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.TEXTURE_COUNT_DEFAULT); - StreamException se = null; - while( null == se && GLMediaPlayer.State.Initialized != mPlayer.getState() ) { - try { - Thread.sleep(16); - } catch (final InterruptedException e) { } - se = mPlayer.getStreamException(); - } - if( null != se ) { - se.printStackTrace(); - throw new RuntimeException(se); - } + playStream(defURI, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.TEXTURE_COUNT_DEFAULT); } /** - * Custom constructor, user needs to issue {@link #initStream(URI, int, int, int)} afterwards. + * Custom constructor, user needs to issue {@link #playStream(URI, int, int, int)} afterwards. */ public MovieCube(final float zoom0, final float rotx, final float roty, final boolean showText) throws IOException { this.zoom0 = zoom0; @@ -156,8 +145,8 @@ public class MovieCube implements GLEventListener { mPlayer = GLMediaPlayerFactory.createDefault(); } - public void initStream(final Uri streamLoc, final int vid, final int aid, final int textureCount) { - mPlayer.initStream(streamLoc, vid, aid, textureCount); + public void playStream(final Uri streamLoc, final int vid, final int aid, final int textureCount) { + mPlayer.playStream(streamLoc, vid, aid, textureCount); System.out.println("pC.1b "+mPlayer); } @@ -179,16 +168,12 @@ public class MovieCube implements GLEventListener { private final GLRegion regionFPS; private float pixelSize1, pixelSize2, underlineSize; - InfoTextRendererGLELBase(final GLProfile glp, final int rmode, final boolean lowPerfDevice) { + InfoTextRendererGLELBase(final GLProfile glp, final int rmode) { // FIXME: Graph TextRenderer does not AA well w/o MSAA and FBO super(rmode, MovieCube.this.textSampleCount); this.setRendererCallbacks(RegionRenderer.defaultBlendEnable, RegionRenderer.defaultBlendDisable); - if( lowPerfDevice ) { - regionFPS = null; - } else { - regionFPS = GLRegion.create(glp, renderModes, null); - System.err.println("RegionFPS "+Region.getRenderModeString(renderModes)+", sampleCount "+textSampleCount[0]+", class "+regionFPS.getClass().getName()); - } + regionFPS = GLRegion.create(glp, renderModes, null); + System.err.println("RegionFPS "+Region.getRenderModeString(renderModes)+", sampleCount "+textSampleCount[0]+", class "+regionFPS.getClass().getName()); staticRGBAColor[0] = 0.1f; staticRGBAColor[1] = 0.1f; staticRGBAColor[2] = 0.1f; @@ -224,6 +209,8 @@ public class MovieCube implements GLEventListener { super.dispose(drawable); } + String text1_old = null; + @Override public void display(final GLAutoDrawable drawable) { final GLAnimatorControl anim = drawable.getAnimator(); @@ -251,12 +238,12 @@ public class MovieCube implements GLEventListener { "; underlineSize "+underlineSize+" "+(pixelScale*underlineSize)+ "; yoff "+yoff1+", yoff2 "+yoff2); */ - final GL gl = drawable.getGL(); + final GL2ES2 gl = drawable.getGL().getGL2ES2(); final String ptsPrec = null != regionFPS ? "3.1" : "3.0"; - final String text1 = String.format("%0"+ptsPrec+"f/%0"+ptsPrec+"f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, v-sync %d", + final String text1 = String.format("%0"+ptsPrec+"f/%0"+ptsPrec+"f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, swap %d", pts, mPlayer.getDuration() / 1000f, mPlayer.getState().toString().toLowerCase(), mPlayer.getPlaySpeed(), mPlayer.getAudioVolume(), - aspect, mPlayer.getFramerate(), lfps, tfps, swapInterval); + aspect, mPlayer.getFramerate(), lfps, tfps, drawable.getGL().getSwapInterval()); final String text2 = String.format("audio: id %d, kbps %d, codec %s", mPlayer.getAID(), mPlayer.getAudioBitrate()/1000, mPlayer.getAudioCodec()); final String text3 = String.format("video: id %d, kbps %d, codec %s", @@ -264,10 +251,11 @@ public class MovieCube implements GLEventListener { final String text4 = mPlayer.getUri().path.decode(); if( displayOSD && null != renderer ) { gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f); - if( null != regionFPS ) { - renderString(drawable, font, pixelSize1, text1, 1 /* col */, -1 /* row */, -1+z_diff, yoff1, 1f+z_diff, regionFPS.clear(gl.getGL2ES2())); // no-cache + if( !text1.equals(text1_old) ) { + renderString(drawable, font, pixelSize1, text1, 1 /* col */, -1 /* row */, -1+z_diff, yoff1, 1f+z_diff, regionFPS.clear(gl)); // clear-cache + text1_old = text1; } else { - renderString(drawable, font, pixelSize1, text1, 1 /* col */, -1 /* row */, -1+z_diff, yoff1, 1f+z_diff, true); + renderRegion(drawable, font, pixelSize1, 1 /* col */, -1 /* row */, -1+z_diff, yoff1, 1f+z_diff, regionFPS); } renderString(drawable, font, pixelSize2, text2, 1 /* col */, 0 /* row */, -1+z_diff, yoff2, 1f+z_diff, true); renderString(drawable, font, pixelSize2, text3, 1 /* col */, 1 /* row */, -1+z_diff, yoff2, 1f+z_diff, true); @@ -337,8 +325,12 @@ public class MovieCube implements GLEventListener { break; } case KeyEvent.VK_SPACE: { - if(GLMediaPlayer.State.Paused == mPlayer.getState()) { - mPlayer.play(); + if( GLMediaPlayer.State.Paused == mPlayer.getState() ) { + mPlayer.resume(); + } else if(GLMediaPlayer.State.Uninitialized == mPlayer.getState()) { + playStream(mPlayer.getUri(), GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 3 /* textureCount */); + } else if( e.isShiftDown() ) { + mPlayer.stop(); } else { mPlayer.pause(false); } @@ -392,12 +384,7 @@ public class MovieCube implements GLEventListener { if(null == mPlayer) { throw new InternalError("mPlayer null"); } - if( GLMediaPlayer.State.Uninitialized == mPlayer.getState() ) { - throw new IllegalStateException("mPlayer in uninitialized state: "+mPlayer); - } - if( GLMediaPlayer.STREAM_ID_NONE == mPlayer.getVID() ) { - // throw new IllegalStateException("mPlayer has no VID/stream selected: "+mPlayer); - } + // final boolean hasVideo = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID(); resetGLState = false; final GL2ES2 gl = drawable.getGL().getGL2ES2(); @@ -409,20 +396,18 @@ public class MovieCube implements GLEventListener { JunitTracer.waitForKey("Init>"); } - if( GLMediaPlayer.State.Initialized == mPlayer.getState() ) { - try { - mPlayer.initGL(gl); - } catch (final Exception e) { - e.printStackTrace(); - if(null != mPlayer) { - mPlayer.destroy(gl); - mPlayer = null; - } - throw new GLException(e); + try { + mPlayer.initGL(gl); + } catch (final Exception e) { + e.printStackTrace(); + if(null != mPlayer) { + mPlayer.destroy(gl); + mPlayer = null; } + throw new GLException(e); } cube.init(drawable); - mPlayer.play(); + mPlayer.resume(); System.out.println("play.0 "+mPlayer); boolean added; @@ -436,8 +421,7 @@ public class MovieCube implements GLEventListener { if( showText ) { final int rmode = drawable.getChosenGLCapabilities().getSampleBuffers() ? 0 : Region.VBAA_RENDERING_BIT; - final boolean lowPerfDevice = gl.isGLES(); - textRendererGLEL = new InfoTextRendererGLELBase(gl.getGLProfile(), rmode, lowPerfDevice); + textRendererGLEL = new InfoTextRendererGLELBase(gl.getGLProfile(), rmode); drawable.addGLEventListener(textRendererGLEL); } } @@ -451,10 +435,6 @@ public class MovieCube implements GLEventListener { @Override public void dispose(final GLAutoDrawable drawable) { System.err.println(Thread.currentThread()+" MovieCube.dispose ... "); - if( null != textRendererGLEL ) { - drawable.disposeGLEventListener(textRendererGLEL, true); - textRendererGLEL = null; - } disposeImpl(drawable, true); } @@ -466,6 +446,10 @@ public class MovieCube implements GLEventListener { window.removeKeyListener(keyAction); } final GL2ES2 gl = drawable.getGL().getGL2ES2(); + if( null != textRendererGLEL ) { + drawable.disposeGLEventListener(textRendererGLEL, true); + textRendererGLEL = null; + } if( disposePlayer ) { mPlayer.destroy(gl); mPlayer=null; @@ -498,7 +482,7 @@ public class MovieCube implements GLEventListener { final long currentPos = System.currentTimeMillis(); if( currentPos - lastPerfPos > 2000 ) { - System.err.println( mPlayer.getPerfString() ); + // System.err.println( mPlayer.getPerfString() ); lastPerfPos = currentPos; } cube.display(drawable); @@ -607,6 +591,7 @@ public class MovieCube implements GLEventListener { anim.stop(); } }); + window.addGLEventListener(mc); window.setSize(width, height); window.setVisible(true); System.err.println("Chosen: "+window.getChosenGLCapabilities()); @@ -626,12 +611,11 @@ public class MovieCube implements GLEventListener { window.setSurfaceSize(mp.getWidth(), mp.getHeight()); } // window.disposeGLEventListener(ms, false /* remove */ ); - mc.resetGLState(); } if( 0 != ( GLMediaEventListener.EVENT_CHANGE_INIT & event_mask ) ) { - window.addGLEventListener(mc); anim.setUpdateFPSFrames(60, null); anim.resetFPSCounter(); + mc.resetGLState(); } if( 0 != ( GLMediaEventListener.EVENT_CHANGE_PLAY & event_mask ) ) { anim.resetFPSCounter(); @@ -649,7 +633,7 @@ public class MovieCube implements GLEventListener { } } }); - mc.initStream(streamLoc, vid, aid, textureCount); + mc.playStream(streamLoc, vid, aid, textureCount); } } diff --git a/src/demos/com/jogamp/opengl/demos/av/MovieSBSStereo.java b/src/demos/com/jogamp/opengl/demos/av/MovieSBSStereo.java index 62e3975dd..519a51a87 100644 --- a/src/demos/com/jogamp/opengl/demos/av/MovieSBSStereo.java +++ b/src/demos/com/jogamp/opengl/demos/av/MovieSBSStereo.java @@ -218,7 +218,7 @@ public class MovieSBSStereo implements StereoGLEventListener { if(GLMediaPlayer.State.Playing == mPlayer.getState()) { mPlayer.pause(false); } else { - mPlayer.play(); + mPlayer.resume(); } } } @@ -245,7 +245,7 @@ public class MovieSBSStereo implements StereoGLEventListener { final int pts0 = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID() ? mPlayer.getVideoPTS() : mPlayer.getAudioPTS(); mPlayer.seek(pts0 + (int) (mPlayer.getDuration() * dp)); } else { - mPlayer.play(); + mPlayer.resume(); rotate = 1; zoom = zoom1; } @@ -286,7 +286,7 @@ public class MovieSBSStereo implements StereoGLEventListener { } case KeyEvent.VK_SPACE: { if(GLMediaPlayer.State.Paused == mPlayer.getState()) { - mPlayer.play(); + mPlayer.resume(); } else { mPlayer.pause(false); } @@ -329,7 +329,7 @@ public class MovieSBSStereo implements StereoGLEventListener { } } }; - /** user needs to issue {@link #initStream(URI, int, int, int)} afterwards. */ + /** user needs to issue {@link #playStream(URI, int, int, int)} afterwards. */ public MovieSBSStereo() throws IllegalStateException { mPlayerScaleOrig = false; mPlayer = GLMediaPlayerFactory.createDefault(); @@ -338,7 +338,7 @@ public class MovieSBSStereo implements StereoGLEventListener { } public void initStream(final Uri streamLoc, final int vid, final int aid, final int textureCount) { - mPlayer.initStream(streamLoc, vid, aid, textureCount); + mPlayer.playStream(streamLoc, vid, aid, textureCount); System.out.println("pC.1b "+mPlayer); } @@ -531,7 +531,7 @@ public class MovieSBSStereo implements StereoGLEventListener { System.out.println(st); } - mPlayer.play(); + mPlayer.resume(); System.out.println("play.0 "+mPlayer); startTime = System.currentTimeMillis(); @@ -861,7 +861,7 @@ public class MovieSBSStereo implements StereoGLEventListener { public void run() { mp.setPlaySpeed(1f); mp.seek(0); - mp.play(); + mp.resume(); } }.start(); } diff --git a/src/demos/com/jogamp/opengl/demos/av/MovieSimple.java b/src/demos/com/jogamp/opengl/demos/av/MovieSimple.java index 42c7b94a5..27735f4c7 100644 --- a/src/demos/com/jogamp/opengl/demos/av/MovieSimple.java +++ b/src/demos/com/jogamp/opengl/demos/av/MovieSimple.java @@ -1,5 +1,5 @@ /** - * Copyright 2012 JogAmp Community. All rights reserved. + * Copyright 2012-2023 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -32,10 +32,8 @@ import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; -import java.nio.FloatBuffer; import com.jogamp.common.net.Uri; -import com.jogamp.common.os.Platform; import com.jogamp.common.util.InterruptSource; import com.jogamp.graph.curve.Region; import com.jogamp.graph.curve.opengl.GLRegion; @@ -53,36 +51,25 @@ import com.jogamp.newt.event.MouseListener; import com.jogamp.newt.event.WindowAdapter; import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.opengl.GLWindow; -import com.jogamp.opengl.GL; import com.jogamp.opengl.GL2ES2; import com.jogamp.opengl.GLAnimatorControl; import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLCapabilities; -import com.jogamp.opengl.GLES2; import com.jogamp.opengl.GLEventListener; import com.jogamp.opengl.GLException; -import com.jogamp.opengl.GLExtensions; import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.GLRunnable; -import com.jogamp.opengl.GLUniformData; import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.demos.es2.TextureSequenceES2; import com.jogamp.opengl.demos.graph.TextRendererGLELBase; import com.jogamp.opengl.demos.util.MiscUtils; -import com.jogamp.opengl.fixedfunc.GLMatrixFunc; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.GLArrayDataServer; import com.jogamp.opengl.util.GLReadBufferUtil; -import com.jogamp.opengl.util.PMVMatrix; import com.jogamp.opengl.util.av.GLMediaPlayer; import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener; import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException; import com.jogamp.opengl.util.av.GLMediaPlayerFactory; -import com.jogamp.opengl.util.glsl.ShaderCode; -import com.jogamp.opengl.util.glsl.ShaderProgram; -import com.jogamp.opengl.util.glsl.ShaderState; -import com.jogamp.opengl.util.texture.Texture; -import com.jogamp.opengl.util.texture.TextureCoords; -import com.jogamp.opengl.util.texture.TextureSequence; import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame; /** @@ -99,9 +86,8 @@ public class MovieSimple implements GLEventListener { private static boolean waitForKey = false; private int surfWidth, surfHeight; private int prevMouseX; // , prevMouseY; - private int rotate = 0; + private final int rotate = 0; private boolean orthoProjection = true; - private float nearPlaneNormalized; private float zoom0; private float zoom1; private float zoom; @@ -111,21 +97,16 @@ public class MovieSimple implements GLEventListener { private int swapInterval = 1; private boolean swapIntervalSet = true; + private TextureSequenceES2 screen=null; private GLMediaPlayer mPlayer; private final boolean mPlayerShared; private boolean mPlayerScaleOrig; - private float[] verts = null; + private final float[] verts = null; private GLArrayDataServer interleavedVBO; private volatile boolean resetGLState = false; private volatile GLAutoDrawable autoDrawable = null; - private ShaderState st; - private PMVMatrix pmvMatrix; - private GLUniformData pmvMatrixUniform; - private static final String shaderBasename = "texsequence_xxx"; - private static final String myTextureLookupName = "myTexture2D"; - /** Blender's Big Buck Bunny: 24f 416p H.264, AAC 48000 Hz, 2 ch, mpeg stream. */ public static final Uri defURI; static { @@ -147,16 +128,12 @@ public class MovieSimple implements GLEventListener { private final float fontSize = 10f; private final GLRegion regionFPS; - InfoTextRendererGLELBase(final GLProfile glp, final int rmode, final boolean lowPerfDevice) { + InfoTextRendererGLELBase(final GLProfile glp, final int rmode) { // FIXME: Graph TextRenderer does not AA well w/o MSAA and FBO super(rmode, textSampleCount); this.setRendererCallbacks(RegionRenderer.defaultBlendEnable, RegionRenderer.defaultBlendDisable); - if( lowPerfDevice ) { - regionFPS = null; - } else { - regionFPS = GLRegion.create(glp, renderModes, null); - System.err.println("RegionFPS "+Region.getRenderModeString(renderModes)+", sampleCount "+textSampleCount[0]+", class "+regionFPS.getClass().getName()); - } + regionFPS = GLRegion.create(glp, renderModes, null); + System.err.println("RegionFPS "+Region.getRenderModeString(renderModes)+", sampleCount "+textSampleCount[0]+", class "+regionFPS.getClass().getName()); staticRGBAColor[0] = 0.9f; staticRGBAColor[1] = 0.9f; staticRGBAColor[2] = 0.9f; @@ -176,6 +153,8 @@ public class MovieSimple implements GLEventListener { super.dispose(drawable); } + String text1_old = null; + @Override public void display(final GLAutoDrawable drawable) { final GLAnimatorControl anim = drawable.getAnimator(); @@ -191,10 +170,10 @@ public class MovieSimple implements GLEventListener { final float aspect = (float)mPlayer.getWidth() / (float)mPlayer.getHeight(); final String ptsPrec = null != regionFPS ? "3.1" : "3.0"; - final String text1 = String.format("%0"+ptsPrec+"f/%0"+ptsPrec+"f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, v-sync %b", + final String text1 = String.format("%0"+ptsPrec+"f/%0"+ptsPrec+"f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, swap %d", pts, mPlayer.getDuration() / 1000f, mPlayer.getState().toString().toLowerCase(), mPlayer.getPlaySpeed(), mPlayer.getAudioVolume(), - aspect, mPlayer.getFramerate(), lfps, tfps, swapIntervalSet); + aspect, mPlayer.getFramerate(), lfps, tfps, drawable.getGL().getSwapInterval()); final String text2 = String.format("audio: id %d, kbps %d, codec %s", mPlayer.getAID(), mPlayer.getAudioBitrate()/1000, mPlayer.getAudioCodec()); final String text3 = String.format("video: id %d, kbps %d, codec %s", @@ -203,11 +182,12 @@ public class MovieSimple implements GLEventListener { if( displayOSD && null != renderer ) { // We share ClearColor w/ MovieSimple's init ! final float pixelSize = FontScale.toPixels(fontSize, dpiH); - if( null != regionFPS ) { - final GL2ES2 gl = drawable.getGL().getGL2ES2(); - renderString(drawable, font, pixelSize, text1, 1 /* col */, 1 /* row */, 0, 0, -1, regionFPS.clear(gl)); // no-cache + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + if( !text1.equals(text1_old) ) { + renderString(drawable, font, pixelSize, text1, 1 /* col */, 1 /* row */, 0, 0, -1, regionFPS.clear(gl)); // clear-cache + text1_old = text1; } else { - renderString(drawable, font, pixelSize, text1, 1 /* col */, 1 /* row */, 0, 0, -1, true); + renderRegion(drawable, font, pixelSize, 1 /* col */, 1 /* row */, 0, 0, -1, regionFPS); } renderString(drawable, font, pixelSize, text2, 1 /* col */, -4 /* row */, 0, height, -1, true); renderString(drawable, font, pixelSize, text3, 1 /* col */, -3 /* row */, 0, height, -1, true); @@ -249,15 +229,18 @@ public class MovieSimple implements GLEventListener { if(GLMediaPlayer.State.Playing == mPlayer.getState()) { mPlayer.pause(false); } else { - mPlayer.play(); + mPlayer.resume(); } } } @Override public void mouseReleased(final MouseEvent e) { if(e.getY()<=surfHeight/2) { - rotate = -1; zoom = zoom0; + if( null != screen ) { + screen.setZoom(zoom); + screen.setZRotation(-1f); + } System.err.println("zoom: "+zoom); } } @@ -276,9 +259,12 @@ public class MovieSimple implements GLEventListener { final int pts0 = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID() ? mPlayer.getVideoPTS() : mPlayer.getAudioPTS(); mPlayer.seek(pts0 + (int) (mPlayer.getDuration() * dp)); } else { - mPlayer.play(); - rotate = 1; + mPlayer.resume(); zoom = zoom1; + if( null != screen ) { + screen.setZoom(zoom); + screen.setZRotation(1f); + } } prevMouseX = x; @@ -288,6 +274,9 @@ public class MovieSimple implements GLEventListener { public void mouseWheelMoved(final MouseEvent e) { if( !e.isShiftDown() ) { zoom += e.getRotation()[1]/10f; // vertical: wheel + if( null != screen ) { + screen.setZoom(zoom); + } System.err.println("zoom: "+zoom); } } }; @@ -326,8 +315,12 @@ public class MovieSimple implements GLEventListener { break; } case KeyEvent.VK_SPACE: { - if(GLMediaPlayer.State.Paused == mPlayer.getState()) { - mPlayer.play(); + if( GLMediaPlayer.State.Paused == mPlayer.getState() ) { + mPlayer.resume(); + } else if(GLMediaPlayer.State.Uninitialized == mPlayer.getState()) { + playStream(mPlayer.getUri(), GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 3 /* textureCount */); + } else if( e.isShiftDown() ) { + mPlayer.stop(); } else { mPlayer.pause(false); } @@ -376,7 +369,7 @@ public class MovieSimple implements GLEventListener { } }; /** - * Default constructor which also issues {@link #initStream(URI, int, int, int)} w/ default values + * Default constructor which also issues {@link #playStream(URI, int, int, int)} w/ default values * and polls until the {@link GLMediaPlayer} is {@link GLMediaPlayer.State#Initialized}. * If {@link GLMediaEventListener#EVENT_CHANGE_EOS} is reached, the stream is started over again. * <p> @@ -394,35 +387,21 @@ public class MovieSimple implements GLEventListener { public void attributesChanged(final GLMediaPlayer mp, final int event_mask, final long when) { System.err.println("MovieCube AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when); System.err.println("MovieCube State: "+mp); - if( 0 != ( GLMediaEventListener.EVENT_CHANGE_SIZE & event_mask ) ) { - resetGLState(); - } if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) { new InterruptSource.Thread() { @Override public void run() { // loop for-ever .. mPlayer.seek(0); - mPlayer.play(); + mPlayer.resume(); } }.start(); } } }); - initStream(defURI, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 3 /* textureCount */); - StreamException se = null; - while( null == se && GLMediaPlayer.State.Initialized != mPlayer.getState() ) { - try { - Thread.sleep(16); - } catch (final InterruptedException e) { } - se = mPlayer.getStreamException(); - } - if( null != se ) { - se.printStackTrace(); - throw new RuntimeException(se); - } + playStream(defURI, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 3 /* textureCount */); } - /** Custom constructor, user needs to issue {@link #initStream(URI, int, int, int)} afterwards. */ + /** Custom constructor, user needs to issue {@link #playStream(URI, int, int, int)} afterwards. */ public MovieSimple(final GLMediaPlayer sharedMediaPlayer) throws IllegalStateException { screenshot = new GLReadBufferUtil(false, false); mPlayer = sharedMediaPlayer; @@ -435,8 +414,8 @@ public class MovieSimple implements GLEventListener { System.out.println("pC.1a shared "+mPlayerShared+", "+mPlayer); } - public void initStream(final Uri streamLoc, final int vid, final int aid, final int textureCount) { - mPlayer.initStream(streamLoc, vid, aid, textureCount); + public void playStream(final Uri streamLoc, final int vid, final int aid, final int textureCount) { + mPlayer.playStream(streamLoc, vid, aid, textureCount); System.out.println("pC.1b "+mPlayer); } @@ -452,73 +431,19 @@ public class MovieSimple implements GLEventListener { public void setOrthoProjection(final boolean v) { orthoProjection=v; } public boolean getOrthoProjection() { return orthoProjection; } - public boolean hasEffect(final int e) { return 0 != ( effects & e ) ; } public void setEffects(final int e) { effects = e; }; - public void setTransparency(final float alpha) { - this.effects |= EFFECT_TRANSPARENT; - this.alpha = alpha; - } + public void setTransparency(final float alpha) { this.alpha = alpha; } public void resetGLState() { resetGLState = true; } - private void initShader(final GL2ES2 gl) { - // Create & Compile the shader objects - final ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, MovieSimple.class, - "../shader", "../shader/bin", shaderBasename, true); - final ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, MovieSimple.class, - "../shader", "../shader/bin", shaderBasename, true); - - boolean preludeGLSLVersion = true; - if( GLES2.GL_TEXTURE_EXTERNAL_OES == mPlayer.getTextureTarget() ) { - if( !gl.isExtensionAvailable(GLExtensions.OES_EGL_image_external) ) { - throw new GLException(GLExtensions.OES_EGL_image_external+" requested but not available"); - } - if( Platform.OSType.ANDROID == Platform.getOSType() && gl.isGLES3() ) { - // Bug on Nexus 10, ES3 - Android 4.3, where - // GL_OES_EGL_image_external extension directive leads to a failure _with_ '#version 300 es' ! - // P0003: Extension 'GL_OES_EGL_image_external' not supported - preludeGLSLVersion = false; - } - } - rsVp.defaultShaderCustomization(gl, preludeGLSLVersion, true); - - int rsFpPos = preludeGLSLVersion ? rsFp.addGLSLVersion(gl) : 0; - rsFpPos = rsFp.insertShaderSource(0, rsFpPos, mPlayer.getRequiredExtensionsShaderStub()); - rsFp.addDefaultShaderPrecision(gl, rsFpPos); - - final String texLookupFuncName = mPlayer.getTextureLookupFunctionName(myTextureLookupName); - rsFp.replaceInShaderSource(myTextureLookupName, texLookupFuncName); - - // Inject TextureSequence shader details - final StringBuilder sFpIns = new StringBuilder(); - sFpIns.append("uniform ").append(mPlayer.getTextureSampler2DType()).append(" mgl_ActiveTexture;\n"); - sFpIns.append(mPlayer.getTextureLookupFragmentShaderImpl()); - rsFp.insertShaderSource(0, "TEXTURE-SEQUENCE-CODE-BEGIN", 0, sFpIns); - - // Create & Link the shader program - final ShaderProgram sp = new ShaderProgram(); - sp.add(rsVp); - sp.add(rsFp); - if(!sp.link(gl, System.err)) { - throw new GLException("Couldn't link program: "+sp); - } - - // Let's manage all our states using ShaderState. - st = new ShaderState(); - st.attachShaderProgram(gl, sp, false); - } - @Override public void init(final GLAutoDrawable drawable) { if(null == mPlayer) { throw new InternalError("mPlayer null"); } - if( GLMediaPlayer.State.Uninitialized == mPlayer.getState() ) { - throw new IllegalStateException("mPlayer in uninitialized state: "+mPlayer); - } - final boolean hasVideo = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID(); + // final boolean hasVideo = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID(); resetGLState = false; zoom0 = orthoProjection ? 0f : -2.5f; @@ -532,118 +457,26 @@ public class MovieSimple implements GLEventListener { System.err.println("Alpha: "+alpha+", opaque "+drawable.getChosenGLCapabilities().isBackgroundOpaque()+ ", "+drawable.getClass().getName()+", "+drawable); + screen = new TextureSequenceES2(mPlayer, mPlayerShared, orthoProjection, zoom); + screen.setEffects(effects); + screen.setTransparency(alpha); + if(waitForKey) { JunitTracer.waitForKey("Init>"); } - final Texture tex; + try { - System.out.println("p0 "+mPlayer+", shared "+mPlayerShared); - if(!mPlayerShared && GLMediaPlayer.State.Initialized == mPlayer.getState() ) { - mPlayer.initGL(gl); - } - System.out.println("p1 "+mPlayer+", shared "+mPlayerShared); - final TextureFrame frame = mPlayer.getLastTexture(); - if( null != frame ) { - if( !hasVideo ) { - throw new InternalError("XXX: "+mPlayer); - } - tex = frame.getTexture(); - if( null == tex ) { - throw new InternalError("XXX: "+mPlayer); - } - } else { - tex = null; - if( hasVideo ) { - throw new InternalError("XXX: "+mPlayer); - } - } - if(!mPlayerShared) { - mPlayer.setTextureMinMagFilter( new int[] { GL.GL_NEAREST, GL.GL_LINEAR } ); - } - } catch (final Exception glex) { - glex.printStackTrace(); - if(!mPlayerShared && null != mPlayer) { + mPlayer.initGL(gl); + } catch (final Exception e) { + e.printStackTrace(); + if(null != mPlayer) { mPlayer.destroy(gl); mPlayer = null; } - throw new GLException(glex); + throw new GLException(e); } + screen.init(drawable); - if( hasVideo ) { - initShader(gl); - - // Push the 1st uniform down the path - st.useProgram(gl, true); - - final int[] viewPort = new int[] { 0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight()}; - pmvMatrix = new PMVMatrix(); - reshapePMV(viewPort[2], viewPort[3]); - pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); - if(!st.uniform(gl, pmvMatrixUniform)) { - throw new GLException("Error setting PMVMatrix in shader: "+st); - } - if(!st.uniform(gl, new GLUniformData("mgl_ActiveTexture", mPlayer.getTextureUnit()))) { - throw new GLException("Error setting mgl_ActiveTexture in shader: "+st); - } - - final float dWidth = drawable.getSurfaceWidth(); - final float dHeight = drawable.getSurfaceHeight(); - final float mWidth = mPlayer.getWidth(); - final float mHeight = mPlayer.getHeight(); - final float mAspect = mWidth/mHeight; - System.err.println("XXX0: mov aspect: "+mAspect); - float xs, ys; - if(orthoProjection) { - if(mPlayerScaleOrig && mWidth < dWidth && mHeight < dHeight) { - xs = mWidth/2f; ys = xs / mAspect; - } else { - xs = dWidth/2f; ys = xs / mAspect; // w>h - } - } else { - if(mPlayerScaleOrig && mWidth < dWidth && mHeight < dHeight) { - xs = mAspect * ( mWidth / dWidth ) ; ys = xs / mAspect ; - } else { - xs = mAspect; ys = 1f; // b>h - } - } - verts = new float[] { -1f*xs, -1f*ys, 0f, // LB - 1f*xs, 1f*ys, 0f // RT - }; - { - System.err.println("XXX0: pixel LB: "+verts[0]+", "+verts[1]+", "+verts[2]); - System.err.println("XXX0: pixel RT: "+verts[3]+", "+verts[4]+", "+verts[5]); - final float[] winLB = new float[3]; - final float[] winRT = new float[3]; - pmvMatrix.gluProject(verts[0], verts[1], verts[2], viewPort, 0, winLB, 0); - pmvMatrix.gluProject(verts[3], verts[4], verts[5], viewPort, 0, winRT, 0); - System.err.println("XXX0: win LB: "+winLB[0]+", "+winLB[1]+", "+winLB[2]); - System.err.println("XXX0: win RT: "+winRT[0]+", "+winRT[1]+", "+winRT[2]); - } - - interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3+4+2, GL.GL_FLOAT, false, 3*4, GL.GL_STATIC_DRAW); - { - interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER); - interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER); - interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER); - } - updateInterleavedVBO(gl, tex); - - st.ownAttribute(interleavedVBO, true); - gl.glClearColor(0.3f, 0.3f, 0.3f, 0.3f); - - gl.glEnable(GL.GL_DEPTH_TEST); - - st.useProgram(gl, false); - - // Let's show the completed shader state .. - System.out.println("iVBO: "+interleavedVBO); - System.out.println(st); - } - - if(!mPlayerShared) { - mPlayer.play(); - System.out.println("play.0 "+mPlayer); - } startTime = System.currentTimeMillis(); final Object upstreamWidget = drawable.getUpstreamWidget(); @@ -655,101 +488,22 @@ public class MovieSimple implements GLEventListener { surfHeight = window.getSurfaceHeight(); } final int rmode = drawable.getChosenGLCapabilities().getSampleBuffers() ? 0 : Region.VBAA_RENDERING_BIT; - final boolean lowPerfDevice = gl.isGLES(); - textRendererGLEL = new InfoTextRendererGLELBase(gl.getGLProfile(), rmode, lowPerfDevice); + textRendererGLEL = new InfoTextRendererGLELBase(gl.getGLProfile(), rmode); drawable.addGLEventListener(textRendererGLEL); } - protected void updateInterleavedVBO(final GL gl, final Texture tex) { - final float ss = 1f, ts = 1f; // scale tex-coord - final boolean wasEnabled = interleavedVBO.enabled(); - interleavedVBO.seal(gl, false); - interleavedVBO.rewind(); - { - final FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer(); - final TextureCoords tc = tex.getImageTexCoords(); - System.err.println("XXX0: "+tc); - System.err.println("XXX0: tex aspect: "+tex.getAspectRatio()); - System.err.println("XXX0: tex y-flip: "+tex.getMustFlipVertically()); - - // left-bottom - ib.put(verts[0]); ib.put(verts[1]); ib.put(verts[2]); - if( hasEffect(EFFECT_GRADIENT_BOTTOM2TOP) ) { - ib.put( 0); ib.put( 0); ib.put( 0); ib.put(alpha); - } else { - ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha); - } - ib.put( tc.left() *ss); ib.put( tc.bottom() *ts); - - // right-bottom - ib.put(verts[3]); ib.put(verts[1]); ib.put(verts[2]); - if( hasEffect(EFFECT_GRADIENT_BOTTOM2TOP) ) { - ib.put( 0); ib.put( 0); ib.put( 0); ib.put(alpha); - } else { - ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha); - } - ib.put( tc.right() *ss); ib.put( tc.bottom() *ts); - - // left-top - ib.put(verts[0]); ib.put(verts[4]); ib.put(verts[2]); - ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha); - ib.put( tc.left() *ss); ib.put( tc.top() *ts); - - // right-top - ib.put(verts[3]); ib.put(verts[4]); ib.put(verts[2]); - ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha); - ib.put( tc.right() *ss); ib.put( tc.top() *ts); - } - interleavedVBO.seal(gl, true); - if( !wasEnabled ) { - interleavedVBO.enableBuffer(gl, false); - } - } - @Override public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { - final GL2ES2 gl = drawable.getGL().getGL2ES2(); if(null == mPlayer) { return; } + screen.reshape(drawable, x, y, width, height); surfWidth = width; surfHeight = height; - - if(null != st) { - reshapePMV(width, height); - st.useProgram(gl, true); - st.uniform(gl, pmvMatrixUniform); - st.useProgram(gl, false); - } - System.out.println("pR "+mPlayer); } - private final float zNear = 1f; - private final float zFar = 10f; - - private void reshapePMV(final int width, final int height) { - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - pmvMatrix.glLoadIdentity(); - if(orthoProjection) { - final float fw = width / 2f; - final float fh = height/ 2f; - pmvMatrix.glOrthof(-fw, fw, -fh, fh, -1.0f, 1.0f); - nearPlaneNormalized = 0f; - } else { - pmvMatrix.gluPerspective(45.0f, (float)width / (float)height, zNear, zFar); - nearPlaneNormalized = 1f/(10f-1f); - } - System.err.println("XXX0: Perspective nearPlaneNormalized: "+nearPlaneNormalized); - - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); - pmvMatrix.glLoadIdentity(); - pmvMatrix.glTranslatef(0, 0, zoom0); - } - @Override public void dispose(final GLAutoDrawable drawable) { autoDrawable = null; - drawable.disposeGLEventListener(textRendererGLEL, true); - textRendererGLEL = null; screenshot.dispose(drawable.getGL()); disposeImpl(drawable, true); } @@ -766,21 +520,21 @@ public class MovieSimple implements GLEventListener { System.out.println("pD.1 "+mPlayer+", disposePlayer "+disposePlayer); final GL2ES2 gl = drawable.getGL().getGL2ES2(); + if( null != textRendererGLEL ) { + drawable.disposeGLEventListener(textRendererGLEL, true); + textRendererGLEL = null; + } if( disposePlayer ) { if(!mPlayerShared) { mPlayer.destroy(gl); + } else { + // mPlayer.stop(gl); } System.out.println("pD.X "+mPlayer); mPlayer=null; } - pmvMatrixUniform = null; - if(null != pmvMatrix) { - pmvMatrix=null; - } - if(null != st) { - st.destroy(gl); - st=null; - } + screen.dispose(drawable); + screen = null; } long lastPerfPos = 0; @@ -791,7 +545,9 @@ public class MovieSimple implements GLEventListener { if( swapIntervalSet ) { final int _swapInterval = swapInterval; gl.setSwapInterval(_swapInterval); // in case switching the drawable (impl. may bound attribute there) - drawable.getAnimator().resetFPSCounter(); + if( null != drawable.getAnimator() ) { + drawable.getAnimator().resetFPSCounter(); + } swapInterval = gl.getSwapInterval(); System.err.println("Swap Interval: "+_swapInterval+" -> "+swapInterval); swapIntervalSet = false; @@ -808,50 +564,10 @@ public class MovieSimple implements GLEventListener { final long currentPos = System.currentTimeMillis(); if( currentPos - lastPerfPos > 2000 ) { - System.err.println( mPlayer.getPerfString() ); + // System.err.println( mPlayer.getPerfString() ); lastPerfPos = currentPos; } - - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - - if(null == st) { - return; - } - - st.useProgram(gl, true); - - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); - pmvMatrix.glLoadIdentity(); - pmvMatrix.glTranslatef(0, 0, zoom); - if(rotate > 0) { - final float ang = ((System.currentTimeMillis() - startTime) * 360.0f) / 8000.0f; - pmvMatrix.glRotatef(ang, 0, 0, 1); - } else { - rotate = 0; - } - st.uniform(gl, pmvMatrixUniform); - interleavedVBO.enableBuffer(gl, true); - Texture tex = null; - if(null!=mPlayer) { - final TextureSequence.TextureFrame texFrame; - if( mPlayerShared ) { - texFrame=mPlayer.getLastTexture(); - } else { - texFrame=mPlayer.getNextTexture(gl); - } - if(null != texFrame) { - tex = texFrame.getTexture(); - gl.glActiveTexture(GL.GL_TEXTURE0+mPlayer.getTextureUnit()); - tex.enable(gl); - tex.bind(gl); - } - } - gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); - if(null != tex) { - tex.disable(gl); - } - interleavedVBO.enableBuffer(gl, false); - st.useProgram(gl, false); + screen.display(drawable); } static class MyGLMediaEventListener implements GLMediaEventListener { @@ -879,15 +595,16 @@ public class MovieSimple implements GLEventListener { window.setSurfaceSize(mp.getWidth(), mp.getHeight()); } // window.disposeGLEventListener(ms, false /* remove */ ); - ms.resetGLState(); + // ms.resetGLState(); } if( 0 != ( GLMediaEventListener.EVENT_CHANGE_INIT & event_mask ) ) { System.err.println("MovieSimple State: INIT"); // Use GLEventListener in all cases [A+V, V, A] - window.addGLEventListener(ms); final GLAnimatorControl anim = window.getAnimator(); anim.setUpdateFPSFrames(60, null); anim.resetFPSCounter(); + ms.resetGLState(); + /** * Kick off player w/o GLEventListener, i.e. for audio only. * @@ -928,7 +645,7 @@ public class MovieSimple implements GLEventListener { public void run() { mp.setPlaySpeed(1f); mp.seek(0); - mp.play(); + mp.resume(); } }.start(); } else { @@ -1100,10 +817,11 @@ public class MovieSimple implements GLEventListener { mss[i].mPlayer.attachObject(WINDOW_KEY, windows[i]); mss[i].mPlayer.addEventListener(myGLMediaEventListener); + anim.add(windows[i]); + windows[i].addGLEventListener(mss[i]); windows[i].setTitle("Player "+i); windows[i].setSize(width, height); windows[i].setVisible(true); - anim.add(windows[i]); final Uri streamLocN; if( 0 == i ) { @@ -1116,7 +834,7 @@ public class MovieSimple implements GLEventListener { } } System.err.println("Win #"+i+": stream "+streamLocN); - mss[i].initStream(streamLocN, vid, aid, textureCount); + mss[i].playStream(streamLocN, vid, aid, textureCount); } } diff --git a/src/demos/com/jogamp/opengl/demos/es2/TextureSequenceCubeES2.java b/src/demos/com/jogamp/opengl/demos/es2/TextureSequenceCubeES2.java index 6a7115143..26a26e3e1 100644 --- a/src/demos/com/jogamp/opengl/demos/es2/TextureSequenceCubeES2.java +++ b/src/demos/com/jogamp/opengl/demos/es2/TextureSequenceCubeES2.java @@ -1,5 +1,5 @@ /** - * Copyright 2012 JogAmp Community. All rights reserved. + * Copyright 2012-2023 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -45,7 +45,6 @@ import com.jogamp.newt.event.MouseAdapter; import com.jogamp.newt.event.MouseEvent; import com.jogamp.newt.event.MouseListener; import com.jogamp.opengl.GLExtensions; -import com.jogamp.opengl.JoglVersion; import com.jogamp.opengl.util.GLArrayDataServer; import com.jogamp.opengl.util.PMVMatrix; import com.jogamp.opengl.util.glsl.ShaderCode; @@ -84,12 +83,15 @@ public class TextureSequenceCubeES2 implements GLEventListener { int ly = 0; boolean first = false; + @Override public void mousePressed(final MouseEvent e) { first = true; } + @Override public void mouseMoved(final MouseEvent e) { first = false; } + @Override public void mouseDragged(final MouseEvent e) { int width, height; final Object source = e.getSource(); @@ -143,6 +145,7 @@ public class TextureSequenceCubeES2 implements GLEventListener { ly = ny; } } + @Override public void mouseWheelMoved(final MouseEvent e) { // System.err.println("XXX "+e); if( !e.isShiftDown() ) { @@ -206,9 +209,9 @@ public class TextureSequenceCubeES2 implements GLEventListener { GLArrayDataServer interleavedVBO, cubeIndicesVBO; + @Override public void init(final GLAutoDrawable drawable) { final GL2ES2 gl = drawable.getGL().getGL2ES2(); - System.err.println(JoglVersion.getGLInfo(gl, null)); final TextureFrame frame = texSeq.getLastTexture(); if( null == frame ) { return; @@ -304,6 +307,7 @@ public class TextureSequenceCubeES2 implements GLEventListener { System.out.println(st); } + @Override public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { final GL2ES2 gl = drawable.getGL().getGL2ES2(); diff --git a/src/demos/com/jogamp/opengl/demos/es2/TextureSequenceES2.java b/src/demos/com/jogamp/opengl/demos/es2/TextureSequenceES2.java new file mode 100644 index 000000000..fd934cb1e --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/es2/TextureSequenceES2.java @@ -0,0 +1,373 @@ +/** + * Copyright 2012-2023 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.demos.es2; + +import java.nio.FloatBuffer; + +import com.jogamp.common.os.Platform; +import com.jogamp.opengl.GL; +import com.jogamp.opengl.GL2ES2; +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLES2; +import com.jogamp.opengl.GLEventListener; +import com.jogamp.opengl.GLException; +import com.jogamp.opengl.GLExtensions; +import com.jogamp.opengl.GLUniformData; +import com.jogamp.opengl.fixedfunc.GLMatrixFunc; +import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; +import com.jogamp.opengl.util.texture.Texture; +import com.jogamp.opengl.util.texture.TextureCoords; +import com.jogamp.opengl.util.texture.TextureSequence; +import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame; + +/** + * Simple planar movie player w/ orthogonal 1:1 projection. + */ +public class TextureSequenceES2 implements GLEventListener { + public static final int EFFECT_NORMAL = 0; + public static final int EFFECT_GRADIENT_BOTTOM2TOP = 1<<1; + public static final int EFFECT_TRANSPARENT = 1<<3; + + private TextureSequence texSeq; + private final boolean texSeqShared; + private ShaderState st; + private PMVMatrix pmvMatrix; + private GLUniformData pmvMatrixUniform; + + private float zrot = 0f; + private final boolean orthoProjection; + private float nearPlaneNormalized; + private float zoom; + + private int effects = EFFECT_NORMAL; + private float alpha = 1.0f; + + private boolean mPlayerScaleOrig; + private float[] verts = null; + private GLArrayDataServer interleavedVBO; + + public TextureSequenceES2(final TextureSequence texSource, final boolean texSeqShared, final boolean orthoProjection, final float zoom0) throws IllegalStateException { + this.texSeq = texSource; + this.texSeqShared = texSeqShared; + this.orthoProjection = orthoProjection; + this.zoom = zoom0; + } + + public void setZoom(final float zoom) { this.zoom = zoom; } + public float getZoom() { return zoom; } + public void setZRotation(final float zrot) { this.zrot = zrot; } + public boolean hasEffect(final int e) { return 0 != ( effects & e ) ; } + public void setEffects(final int e) { effects = e; }; + public void setTransparency(final float alpha) { + this.effects |= EFFECT_TRANSPARENT; + this.alpha = alpha; + } + + private static final String shaderBasename = "texsequence_xxx"; + private static final String myTextureLookupName = "myTexture2D"; + + private void initShader(final GL2ES2 gl) { + // Create & Compile the shader objects + final ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), + "shader", "shader/bin", shaderBasename, true); + final ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), + "shader", "shader/bin", shaderBasename, true); + + boolean preludeGLSLVersion = true; + if( GLES2.GL_TEXTURE_EXTERNAL_OES == texSeq.getTextureTarget() ) { + if( !gl.isExtensionAvailable(GLExtensions.OES_EGL_image_external) ) { + throw new GLException(GLExtensions.OES_EGL_image_external+" requested but not available"); + } + if( Platform.OSType.ANDROID == Platform.getOSType() && gl.isGLES3() ) { + // Bug on Nexus 10, ES3 - Android 4.3, where + // GL_OES_EGL_image_external extension directive leads to a failure _with_ '#version 300 es' ! + // P0003: Extension 'GL_OES_EGL_image_external' not supported + preludeGLSLVersion = false; + } + } + rsVp.defaultShaderCustomization(gl, preludeGLSLVersion, true); + + int rsFpPos = preludeGLSLVersion ? rsFp.addGLSLVersion(gl) : 0; + rsFpPos = rsFp.insertShaderSource(0, rsFpPos, texSeq.getRequiredExtensionsShaderStub()); + rsFp.addDefaultShaderPrecision(gl, rsFpPos); + + final String texLookupFuncName = texSeq.getTextureLookupFunctionName(myTextureLookupName); + rsFp.replaceInShaderSource(myTextureLookupName, texLookupFuncName); + + // Inject TextureSequence shader details + final StringBuilder sFpIns = new StringBuilder(); + sFpIns.append("uniform ").append(texSeq.getTextureSampler2DType()).append(" mgl_ActiveTexture;\n"); + sFpIns.append(texSeq.getTextureLookupFragmentShaderImpl()); + rsFp.insertShaderSource(0, "TEXTURE-SEQUENCE-CODE-BEGIN", 0, sFpIns); + + // Create & Link the shader program + final ShaderProgram sp = new ShaderProgram(); + sp.add(rsVp); + sp.add(rsFp); + if(!sp.link(gl, System.err)) { + throw new GLException("Couldn't link program: "+sp); + } + + // Let's manage all our states using ShaderState. + st = new ShaderState(); + st.attachShaderProgram(gl, sp, false); + } + + @Override + public void init(final GLAutoDrawable drawable) { + if(null == texSeq) { + throw new InternalError("texSeq null"); + } + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + final TextureFrame frame = texSeq.getLastTexture(); + if( null == frame ) { + return; + } + final Texture tex = frame.getTexture(); + + initShader(gl); + + // Push the 1st uniform down the path + st.useProgram(gl, true); + + final int[] viewPort = new int[] { 0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight()}; + pmvMatrix = new PMVMatrix(); + reshapePMV(viewPort[2], viewPort[3]); + pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + if(!st.uniform(gl, pmvMatrixUniform)) { + throw new GLException("Error setting PMVMatrix in shader: "+st); + } + if(!st.uniform(gl, new GLUniformData("mgl_ActiveTexture", texSeq.getTextureUnit()))) { + throw new GLException("Error setting mgl_ActiveTexture in shader: "+st); + } + + final float dWidth = drawable.getSurfaceWidth(); + final float dHeight = drawable.getSurfaceHeight(); + final float mWidth = tex.getImageWidth(); + final float mHeight = tex.getImageHeight(); + final float mAspect = mWidth/mHeight; + System.err.println("XXX0: mov aspect: "+mAspect); + float xs, ys; + if(orthoProjection) { + if(mPlayerScaleOrig && mWidth < dWidth && mHeight < dHeight) { + xs = mWidth/2f; ys = xs / mAspect; + } else { + xs = dWidth/2f; ys = xs / mAspect; // w>h + } + } else { + if(mPlayerScaleOrig && mWidth < dWidth && mHeight < dHeight) { + xs = mAspect * ( mWidth / dWidth ) ; ys = xs / mAspect ; + } else { + xs = mAspect; ys = 1f; // b>h + } + } + verts = new float[] { -1f*xs, -1f*ys, 0f, // LB + 1f*xs, 1f*ys, 0f // RT + }; + { + System.err.println("XXX0: pixel LB: "+verts[0]+", "+verts[1]+", "+verts[2]); + System.err.println("XXX0: pixel RT: "+verts[3]+", "+verts[4]+", "+verts[5]); + final float[] winLB = new float[3]; + final float[] winRT = new float[3]; + pmvMatrix.gluProject(verts[0], verts[1], verts[2], viewPort, 0, winLB, 0); + pmvMatrix.gluProject(verts[3], verts[4], verts[5], viewPort, 0, winRT, 0); + System.err.println("XXX0: win LB: "+winLB[0]+", "+winLB[1]+", "+winLB[2]); + System.err.println("XXX0: win RT: "+winRT[0]+", "+winRT[1]+", "+winRT[2]); + } + + interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3+4+2, GL.GL_FLOAT, false, 3*4, GL.GL_STATIC_DRAW); + { + interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER); + interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER); + interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER); + } + updateInterleavedVBO(gl, tex); + + st.ownAttribute(interleavedVBO, true); + gl.glClearColor(0.3f, 0.3f, 0.3f, 0.3f); + + gl.glEnable(GL.GL_DEPTH_TEST); + + st.useProgram(gl, false); + + // Let's show the completed shader state .. + System.out.println("iVBO: "+interleavedVBO); + System.out.println(st); + } + + protected void updateInterleavedVBO(final GL gl, final Texture tex) { + final float ss = 1f, ts = 1f; // scale tex-coord + final boolean wasEnabled = interleavedVBO.enabled(); + interleavedVBO.seal(gl, false); + interleavedVBO.rewind(); + { + final FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer(); + final TextureCoords tc = tex.getImageTexCoords(); + System.err.println("XXX0: "+tc); + System.err.println("XXX0: tex aspect: "+tex.getAspectRatio()); + System.err.println("XXX0: tex y-flip: "+tex.getMustFlipVertically()); + + // left-bottom + ib.put(verts[0]); ib.put(verts[1]); ib.put(verts[2]); + if( hasEffect(EFFECT_GRADIENT_BOTTOM2TOP) ) { + ib.put( 0); ib.put( 0); ib.put( 0); ib.put(alpha); + } else { + ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha); + } + ib.put( tc.left() *ss); ib.put( tc.bottom() *ts); + + // right-bottom + ib.put(verts[3]); ib.put(verts[1]); ib.put(verts[2]); + if( hasEffect(EFFECT_GRADIENT_BOTTOM2TOP) ) { + ib.put( 0); ib.put( 0); ib.put( 0); ib.put(alpha); + } else { + ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha); + } + ib.put( tc.right() *ss); ib.put( tc.bottom() *ts); + + // left-top + ib.put(verts[0]); ib.put(verts[4]); ib.put(verts[2]); + ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha); + ib.put( tc.left() *ss); ib.put( tc.top() *ts); + + // right-top + ib.put(verts[3]); ib.put(verts[4]); ib.put(verts[2]); + ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha); + ib.put( tc.right() *ss); ib.put( tc.top() *ts); + } + interleavedVBO.seal(gl, true); + if( !wasEnabled ) { + interleavedVBO.enableBuffer(gl, false); + } + } + + @Override + public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + if(null != st) { + reshapePMV(width, height); + st.useProgram(gl, true); + st.uniform(gl, pmvMatrixUniform); + st.useProgram(gl, false); + } + + System.out.println("pR "+texSeq); + } + + private final float zNear = 1f; + private final float zFar = 10f; + + private void reshapePMV(final int width, final int height) { + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + if(orthoProjection) { + final float fw = width / 2f; + final float fh = height/ 2f; + pmvMatrix.glOrthof(-fw, fw, -fh, fh, -1.0f, 1.0f); + nearPlaneNormalized = 0f; + } else { + pmvMatrix.gluPerspective(45.0f, (float)width / (float)height, zNear, zFar); + nearPlaneNormalized = 1f/(10f-1f); + } + System.err.println("XXX0: Perspective nearPlaneNormalized: "+nearPlaneNormalized); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glTranslatef(0, 0, zoom); + } + + @Override + public void dispose(final GLAutoDrawable drawable) { + if(null == texSeq) { return; } + disposeImpl(drawable, true); + } + private void disposeImpl(final GLAutoDrawable drawable, final boolean disposeTexSeq) { + if( disposeTexSeq ) { + texSeq = null; + } + pmvMatrixUniform = null; + pmvMatrix=null; + if(null != st) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + st.destroy(gl); + st=null; + } + } + + @Override + public void display(final GLAutoDrawable drawable) { + if(null == texSeq) { return; } + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + if(null == st) { + return; + } + + st.useProgram(gl, true); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glTranslatef(0, 0, zoom); + if(zrot > 0f) { + pmvMatrix.glRotatef(zrot, 0, 0, 1); + } else { + zrot = 0; + } + st.uniform(gl, pmvMatrixUniform); + interleavedVBO.enableBuffer(gl, true); + Texture tex = null; + if(null!=texSeq) { + final TextureSequence.TextureFrame texFrame; + if( texSeqShared ) { + texFrame = texSeq.getLastTexture(); + } else { + texFrame = texSeq.getNextTexture(gl); + } + if(null != texFrame) { + tex = texFrame.getTexture(); + gl.glActiveTexture(GL.GL_TEXTURE0+texSeq.getTextureUnit()); + tex.enable(gl); + tex.bind(gl); + } + } + gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); + if(null != tex) { + tex.disable(gl); + } + interleavedVBO.enableBuffer(gl, false); + st.useProgram(gl, false); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/graph/TextRendererGLELBase.java b/src/demos/com/jogamp/opengl/demos/graph/TextRendererGLELBase.java index 61240e4a2..7ab5e6b8c 100644 --- a/src/demos/com/jogamp/opengl/demos/graph/TextRendererGLELBase.java +++ b/src/demos/com/jogamp/opengl/demos/graph/TextRendererGLELBase.java @@ -133,6 +133,10 @@ public abstract class TextRendererGLELBase implements GLEventListener { public void setFlipVerticalInGLOrientation(final boolean v) { flipVerticalInGLOrientation=v; } public final RegionRenderer getRenderer() { return renderer; } public final TextRegionUtil getTextRenderUtil() { return textRenderUtil; } + public int[] getVBAASampleCount() { return this.vbaaSampleCount; } + + public PMVMatrix getMatrix() { return rs.getMatrix(); }; + public boolean isMatrixShared() { return !exclusivePMVMatrix; }; @Override public void init(final GLAutoDrawable drawable) { @@ -276,9 +280,9 @@ public abstract class TextRendererGLELBase implements GLEventListener { if( cacheRegion ) { textRenderUtil.drawString3D(gl, renderer, font, text, null, vbaaSampleCount); } else if( null != region ) { - TextRegionUtil.drawString3D(gl, region, renderer, font, text, null, vbaaSampleCount, tempT1, tempT1); + TextRegionUtil.drawString3D(gl, region, renderer, font, text, null, vbaaSampleCount, tempT1, tempT2); } else { - TextRegionUtil.drawString3D(gl, renderModes, renderer, font, text, null, vbaaSampleCount, tempT1, tempT1); + TextRegionUtil.drawString3D(gl, renderModes, renderer, font, text, null, vbaaSampleCount, tempT1, tempT2); } renderer.enable(gl, false); @@ -288,4 +292,47 @@ public abstract class TextRendererGLELBase implements GLEventListener { lastRow = row + newLineCount; } } + public void renderRegion(final GLAutoDrawable drawable, + final Font font, final float pixelSize, + final int column, final int row, + final float tx, final float ty, final float tz, final GLRegion region) { + if( null != renderer ) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + float dx = tx; + float dy; + + if( !exclusivePMVMatrix ) { + dy = 1f-ty; + } else { + final int height = drawable.getSurfaceHeight(); + dy = height-ty; + } + final float sxy = pixelScale * pixelSize; + final float lineHeight = font.getLineHeight(); + dx += sxy * font.getAdvanceWidth('X') * column; + dy -= sxy * lineHeight * ( row + 1 ); + + final PMVMatrix pmvMatrix = rs.getMatrix(); + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + if( !exclusivePMVMatrix ) { + pmvMatrix.glPushMatrix(); + } else { + pmvMatrix.glLoadIdentity(); + } + pmvMatrix.glTranslatef(dx, dy, tz); + if( flipVerticalInGLOrientation && drawable.isGLOriented() ) { + pmvMatrix.glScalef(sxy, -1f*sxy, 1.0f); + } else { + pmvMatrix.glScalef(sxy, sxy, 1.0f); + } + renderer.enable(gl, true); + region.draw(gl, renderer, vbaaSampleCount); + renderer.enable(gl, false); + + if( !exclusivePMVMatrix ) { + pmvMatrix.glPopMatrix(); + } + } + } } diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/GPUUISceneGLListener0A.java b/src/demos/com/jogamp/opengl/demos/graph/ui/GPUUISceneGLListener0A.java index 990143de8..c73cb7526 100644 --- a/src/demos/com/jogamp/opengl/demos/graph/ui/GPUUISceneGLListener0A.java +++ b/src/demos/com/jogamp/opengl/demos/graph/ui/GPUUISceneGLListener0A.java @@ -585,7 +585,7 @@ public class GPUUISceneGLListener0A implements GLEventListener { mPlayer.setAudioVolume( mPlayerButton.isToggleOn() ? 1f : 0f ); } } ); buttons.add(mPlayerButton); - mPlayer.initStream(filmURL, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.TEXTURE_COUNT_DEFAULT); + mPlayer.playStream(filmURL, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.TEXTURE_COUNT_DEFAULT); } if( true ) { final ImageSequence imgSeq = new ImageSequence(texUnitImageButton, true); @@ -943,6 +943,7 @@ public class GPUUISceneGLListener0A implements GLEventListener { @Override public void mouseWheelMoved(final MouseEvent e) { final Shape.EventInfo shapeEvent = (Shape.EventInfo) e.getAttachment(); + /** final boolean isOnscreen = PointerClass.Onscreen == e.getPointerType(0).getPointerClass(); if( 0 == ( ~InputEvent.BUTTONALL_MASK & e.getModifiers() ) && !isOnscreen ) { // offscreen vertical mouse wheel zoom @@ -958,8 +959,14 @@ public class GPUUISceneGLListener0A implements GLEventListener { VectorUtil.scaleVec3(rot, rot, 2f); } shapeEvent.shape.getRotation().rotateByEuler( rot ); - } + } */ + final float[] rot = VectorUtil.scaleVec3(e.getRotation(), e.getRotation(), FloatUtil.PI / 180.0f); + // swap axis for onscreen rotation matching natural feel + final float tmp = rot[0]; rot[0] = rot[1]; rot[1] = tmp; + VectorUtil.scaleVec3(rot, rot, 2f); + shapeEvent.shape.getRotation().rotateByEuler( rot ); } + /** @Override public void gestureDetected(final GestureEvent e) { final Shape.EventInfo shapeEvent = (Shape.EventInfo) e.getAttachment(); @@ -969,5 +976,6 @@ public class GPUUISceneGLListener0A implements GLEventListener { System.err.println("Rotate.Zoom.G: "+tz); shapeEvent.shape.move(0f, 0f, tz); } - } }; + } */ + }; } diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/GPUUISceneTextAnim01.java b/src/demos/com/jogamp/opengl/demos/graph/ui/GPUUISceneTextAnim01.java index 45bfd53f1..8658fdf4d 100644 --- a/src/demos/com/jogamp/opengl/demos/graph/ui/GPUUISceneTextAnim01.java +++ b/src/demos/com/jogamp/opengl/demos/graph/ui/GPUUISceneTextAnim01.java @@ -317,35 +317,5 @@ public class GPUUISceneTextAnim01 implements GLEventListener { actionText = String.format((Locale)null, "Pos %6.2f / %6.2f / %6.2f", tx[0], tx[1], tx[2]); } } - - @Override - public void mouseWheelMoved(final MouseEvent e) { - final Shape.EventInfo shapeEvent = (Shape.EventInfo) e.getAttachment(); - final boolean isOnscreen = PointerClass.Onscreen == e.getPointerType(0).getPointerClass(); - if( 0 == ( ~InputEvent.BUTTONALL_MASK & e.getModifiers() ) && !isOnscreen ) { - // offscreen vertical mouse wheel zoom - final float tz = 100f*e.getRotation()[1]; // vertical: wheel - System.err.println("Rotate.Zoom.W: "+tz); - shapeEvent.shape.move(0f, 0f, tz); - } else if( isOnscreen || e.isControlDown() ) { - final float[] rot = VectorUtil.scaleVec3(e.getRotation(), e.getRotation(), FloatUtil.PI / 180.0f); - if( isOnscreen ) { - System.err.println("XXX: "+e); - // swap axis for onscreen rotation matching natural feel - final float tmp = rot[0]; rot[0] = rot[1]; rot[1] = tmp; - VectorUtil.scaleVec3(rot, rot, 2f); - } - shapeEvent.shape.getRotation().rotateByEuler( rot ); - } - } - @Override - public void gestureDetected(final GestureEvent e) { - final Shape.EventInfo shapeEvent = (Shape.EventInfo) e.getAttachment(); - if( e instanceof PinchToZoomGesture.ZoomEvent ) { - final PinchToZoomGesture.ZoomEvent ze = (PinchToZoomGesture.ZoomEvent) e; - final float tz = ze.getDelta() * ze.getScale(); - System.err.println("Rotate.Zoom.G: "+tz); - shapeEvent.shape.move(0f, 0f, tz); - } - } }; + }; } diff --git a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/MediaButton.java b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/MediaButton.java index 290abba6e..241fad389 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/MediaButton.java +++ b/src/graphui/classes/com/jogamp/graph/ui/gl/shapes/MediaButton.java @@ -105,7 +105,7 @@ public class MediaButton extends TexSeqButton { public void run() { // loop for-ever .. mPlayer.seek(0); - mPlayer.play(); + mPlayer.resume(); } }.start(); } else if( 0 != ( GLMediaEventListener.EVENT_CHANGE_ERR & event_mask ) ) { final StreamException se = mPlayer.getStreamException(); @@ -128,7 +128,7 @@ public class MediaButton extends TexSeqButton { try { mPlayer.initGL(gl); mPlayer.setAudioVolume( 0f ); - mPlayer.play(); + mPlayer.resume(); markStateDirty(); } catch (final Exception e) { e.printStackTrace(); 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. * </p> * <p> - * 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 <a href="#streamIDs">stream id</a>'s. * </p> * <p> @@ -56,7 +57,7 @@ import com.jogamp.opengl.util.TimeFrameI; * <p> * Most of the stream processing is performed on the decoding thread, a.k.a. <i>StreamWorker</i>: * <ul> - * <li>Stream initialization triggered by {@link #initStream(Uri, int, int, int) initStream(..)} - User gets notified whether the stream has been initialized or not via {@link GLMediaEventListener#attributesChanged(GLMediaPlayer, int, long) attributesChanges(..)}.</li> + * <li>Stream initialization triggered by {@link #playStream(Uri, int, int, int) playStream(..)} - User gets notified whether the stream has been initialized or not via {@link GLMediaEventListener#attributesChanged(GLMediaPlayer, int, long) attributesChanges(..)}.</li> * <li>Stream decoding - User gets notified of a new frame via {@link GLMediaEventListener#newFrameAvailable(GLMediaPlayer, com.jogamp.opengl.util.texture.TextureSequence.TextureFrame, long) newFrameAvailable(...)}.</li> * <li>Caught <a href="#streamerror">exceptions on the decoding thread</a> are delivered as {@link StreamException}s.</li> * </ul> @@ -82,16 +83,17 @@ import com.jogamp.opengl.util.TimeFrameI; * <p> * <table border="1"> * <tr><th>Action</th> <th>{@link State} Before</th> <th>{@link State} After</th> <th>{@link GLMediaEventListener Event}</th></tr> - * <tr><td>{@link #initStream(Uri, int, int, int)}</td> <td>{@link State#Uninitialized Uninitialized}</td> <td>{@link State#Initialized Initialized}<sup><a href="#streamworker">1</a></sup>, {@link State#Uninitialized Uninitialized}</td> <td>{@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} )</td></tr> - * <tr><td>{@link #initGL(GL)}</td> <td>{@link State#Initialized Initialized}</td> <td>{@link State#Paused Paused}, , {@link State#Uninitialized Uninitialized}</td> <td>{@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} )</td></tr> - * <tr><td>{@link #play()}</td> <td>{@link State#Paused Paused}</td> <td>{@link State#Playing Playing}</td> <td>{@link GLMediaEventListener#EVENT_CHANGE_PLAY EVENT_CHANGE_PLAY}</td></tr> + * <tr><td>{@link #playStream(Uri, int, int, int)}</td> <td>{@link State#Uninitialized Uninitialized}</td> <td>{@link State#Initialized Initialized}<sup><a href="#streamworker">1</a></sup>, {@link State#Uninitialized Uninitialized}</td> <td>{@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} )</td></tr> + * <tr><td>{@link #initGL(GL)}</td> <td>{@link State#Initialized Initialized}, {@link State#Uninitialized Uninitialized} </td> <td>{@link State#Playing Playing}, {@link State#Uninitialized Uninitialized}</td> <td>{@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} )</td></tr> * <tr><td>{@link #pause(boolean)}</td> <td>{@link State#Playing Playing}</td> <td>{@link State#Paused Paused}</td> <td>{@link GLMediaEventListener#EVENT_CHANGE_PAUSE EVENT_CHANGE_PAUSE}</td></tr> + * <tr><td>{@link #resume()}</td> <td>{@link State#Paused Paused}</td> <td>{@link State#Playing Playing}</td> <td>{@link GLMediaEventListener#EVENT_CHANGE_PLAY EVENT_CHANGE_PLAY}</td></tr> + * <tr><td>{@link #stop()}</td> <td>{@link State#Playing Playing}, {@link State#Paused Paused}</td> <td>{@link State#Uninitialized Uninitialized}</td> <td>{@link GLMediaEventListener#EVENT_CHANGE_PAUSE EVENT_CHANGE_PAUSE}</td></tr> * <tr><td>{@link #seek(int)}</td> <td>{@link State#Paused Paused}, {@link State#Playing Playing}</td> <td>{@link State#Paused Paused}, {@link State#Playing Playing}</td> <td>none</td></tr> - * <tr><td>{@link #getNextTexture(GL)}</td> <td>{@link State#Paused Paused}, {@link State#Playing Playing}</td> <td>{@link State#Paused Paused}, {@link State#Playing Playing}</td> <td>none</td></tr> - * <tr><td>{@link #getLastTexture()}</td> <td>{@link State#Paused Paused}, {@link State#Playing Playing}</td> <td>{@link State#Paused Paused}, {@link State#Playing Playing}</td> <td>none</td></tr> + * <tr><td>{@link #getNextTexture(GL)}</td> <td><i>any</i></td> <td><i>same</i></td> <td>none</td></tr> + * <tr><td>{@link #getLastTexture()}</td> <td><i>any</i></td> <td><i>same</i></td> <td>none</td></tr> * <tr><td>{@link TextureFrame#END_OF_STREAM_PTS END_OF_STREAM}</td> <td>{@link State#Playing Playing}</td> <td>{@link State#Paused Paused}</td> <td>{@link GLMediaEventListener#EVENT_CHANGE_EOS EVENT_CHANGE_EOS} + {@link GLMediaEventListener#EVENT_CHANGE_PAUSE EVENT_CHANGE_PAUSE}</td></tr> - * <tr><td>{@link StreamException}</td> <td>ANY</td> <td>{@link State#Paused Paused}, {@link State#Uninitialized Uninitialized}</td> <td>{@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} )</td></tr> - * <tr><td>{@link #destroy(GL)}</td> <td>ANY</td> <td>{@link State#Uninitialized Uninitialized}</td> <td>{@link GLMediaEventListener#EVENT_CHANGE_UNINIT EVENT_CHANGE_UNINIT}</td></tr> + * <tr><td>{@link StreamException}</td> <td><i>any</i></td> <td>{@link State#Paused Paused}, {@link State#Uninitialized Uninitialized}</td> <td>{@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} )</td></tr> + * <tr><td>{@link #destroy(GL)}</td> <td><i>any</i></td> <td>{@link State#Uninitialized Uninitialized}</td> <td>{@link GLMediaEventListener#EVENT_CHANGE_UNINIT EVENT_CHANGE_UNINIT}</td></tr> * </table> * </p> * @@ -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 <code>null</code> if none occured. @@ -389,7 +392,7 @@ public interface GLMediaPlayer extends TextureSequence { * <p> * <a href="#lifecycle">Lifecycle</a>: {@link State#Initialized} -> {@link State#Paused} or {@link State#Initialized} * </p> - * Argument <code>gl</code> is ignored if video is muted, see {@link #initStream(Uri, int, int, int)}. + * Argument <code>gl</code> is ignored if video is muted, see {@link #playStream(Uri, int, int, int)}. * * @param gl current GL object. Maybe <code>null</code>, 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. * <p> - * 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. * </p> */ @@ -416,6 +419,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}. + * <p> + * <a href="#lifecycle">Lifecycle</a>: <code>ANY</code> -> {@link State#Uninitialized} + * </p> + */ + public State stop(); + + /** * Sets the playback speed. * <p> * To simplify test, play speed is <i>normalized</i>, i.e. @@ -452,7 +463,7 @@ public interface GLMediaPlayer extends TextureSequence { * <a href="#lifecycle">Lifecycle</a>: {@link State#Paused} -> {@link State#Playing} * </p> */ - public State play(); + public State resume(); /** * Pauses the <i>StreamWorker</i> decoding thread. @@ -460,7 +471,7 @@ public interface GLMediaPlayer extends TextureSequence { * <a href="#lifecycle">Lifecycle</a>: {@link State#Playing} -> {@link State#Paused} * </p> * <p> - * If a <i>new</i> frame is desired after the next {@link #play()} call, + * If a <i>new</i> frame is desired after the next {@link #resume()} call, * e.g. to make a snapshot of a camera input stream, * <code>flush</code> shall be set to <code>true</code>. * </p> @@ -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(); diff --git a/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java b/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java index 09d2dfda0..06eca7128 100644 --- a/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java +++ b/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java @@ -136,7 +136,7 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl { } @Override - protected final boolean playImpl() { + protected final boolean resumeImpl() { playStart = Platform.currentTimeMillis(); if(null != mp) { try { @@ -212,7 +212,7 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl { protected final int getAudioPTSImpl() { return null != mp ? mp.getCurrentPosition() : 0; } @Override - protected final void destroyImpl(final GL gl) { + protected final void destroyImpl() { if(null != mp) { wakeUp(false); try { @@ -239,12 +239,18 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl { } } + @Override + protected void stopImpl() { + destroyImpl(); + } + public static class SurfaceTextureFrame extends TextureSequence.TextureFrame { public SurfaceTextureFrame(final Texture t, final SurfaceTexture stex) { super(t); this.surfaceTex = stex; } + @Override public String toString() { return "SurfaceTextureFrame[pts " + pts + " ms, l " + duration + " ms, texID "+ texture.getTextureObject() + ", " + surfaceTex + "]"; } diff --git a/src/jogl/classes/jogamp/opengl/openal/av/ALAudioSink.java b/src/jogl/classes/jogamp/opengl/openal/av/ALAudioSink.java index bdd9b6c95..c52c59f17 100644 --- a/src/jogl/classes/jogamp/opengl/openal/av/ALAudioSink.java +++ b/src/jogl/classes/jogamp/opengl/openal/av/ALAudioSink.java @@ -89,6 +89,7 @@ public class ALAudioSink implements AudioSink { /** Get this frame's OpenAL buffer name */ public final int getALBuffer() { return alBuffer; } + @Override public String toString() { return "ALAudioFrame[pts " + pts + " ms, l " + duration + " ms, " + byteSize + " bytes, buffer "+alBuffer+"]"; } diff --git a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java index 01e04f6de..d29464552 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java +++ b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java @@ -28,6 +28,9 @@ package jogamp.opengl.util.av; import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URLConnection; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -46,9 +49,11 @@ import com.jogamp.opengl.GLProfile; import jogamp.opengl.Debug; import com.jogamp.common.net.UriQueryProps; +import com.jogamp.common.nio.Buffers; import com.jogamp.common.ExceptionUtils; import com.jogamp.common.net.Uri; import com.jogamp.common.os.Platform; +import com.jogamp.common.util.IOUtil; import com.jogamp.common.util.InterruptSource; import com.jogamp.common.util.InterruptedRuntimeException; import com.jogamp.common.util.LFRingbuffer; @@ -60,6 +65,8 @@ import com.jogamp.opengl.util.av.AudioSink; import com.jogamp.opengl.util.av.GLMediaPlayer; import com.jogamp.opengl.util.glsl.ShaderCode; import com.jogamp.opengl.util.texture.Texture; +import com.jogamp.opengl.util.texture.TextureData; +import com.jogamp.opengl.util.texture.TextureIO; import com.jogamp.opengl.util.texture.TextureSequence; import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame; @@ -96,12 +103,12 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { private final int[] texWrapST = { GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE }; /** User requested URI stream location. */ - private Uri streamLoc = null; + private Uri streamLoc; /** * In case {@link #streamLoc} is a {@link GLMediaPlayer#CameraInputScheme}, * {@link #cameraPath} holds the URI's path portion - * as parsed in {@link #initStream(Uri, int, int, int)}. + * as parsed in {@link #playStream(Uri, int, int, int)}. * @see #cameraProps */ protected Uri.Encoded cameraPath = null; @@ -112,9 +119,9 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { private float audioVolume = 1.0f; /** Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */ - private int vid = GLMediaPlayer.STREAM_ID_AUTO; + private int vid = GLMediaPlayer.STREAM_ID_NONE; /** Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */ - private int aid = GLMediaPlayer.STREAM_ID_AUTO; + private int aid = GLMediaPlayer.STREAM_ID_NONE; /** Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */ private int width = 0; /** Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */ @@ -202,6 +209,9 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { this.texUnit = 0; this.textureFragmentShaderHashCode = 0; this.state = State.Uninitialized; + try { + streamLoc = Uri.cast("https://no/stream/"); + } catch (final URISyntaxException e) { } } @Override @@ -237,15 +247,8 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { @Override public final int[] getTextureWrapST() { return texWrapST; } - private final void checkGLInit() { - if(State.Uninitialized == state || State.Initialized == state ) { - throw new IllegalStateException("GL not initialized: "+this); - } - } - @Override - public String getRequiredExtensionsShaderStub() throws IllegalStateException { - checkGLInit(); + public String getRequiredExtensionsShaderStub() { if(GLES2.GL_TEXTURE_EXTERNAL_OES == textureTarget) { return ShaderCode.createExtensionDirective(GLExtensions.OES_EGL_image_external, ShaderCode.ENABLE); } @@ -253,8 +256,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { } @Override - public String getTextureSampler2DType() throws IllegalStateException { - checkGLInit(); + public String getTextureSampler2DType() { switch(textureTarget) { case GL.GL_TEXTURE_2D: case GL2GL3.GL_TEXTURE_RECTANGLE: @@ -273,8 +275,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { * if not overridden by specialization. */ @Override - public String getTextureLookupFunctionName(final String desiredFuncName) throws IllegalStateException { - checkGLInit(); + public String getTextureLookupFunctionName(final String desiredFuncName) { return "texture2D"; } @@ -286,8 +287,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { * if not overridden by specialization. */ @Override - public String getTextureLookupFragmentShaderImpl() throws IllegalStateException { - checkGLInit(); + public String getTextureLookupFragmentShaderImpl() { return ""; } @@ -335,12 +335,12 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { protected final void setState(final State s) { state=s; } @Override - public final State play() { + public final State resume() { synchronized( stateLock ) { final State preState = state; switch( state ) { case Paused: - if( playImpl() ) { + if( resumeImpl() ) { resetAVPTS(); if( null != audioSink ) { audioSink.play(); // cont. w/ new data @@ -356,7 +356,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { return state; } } - protected abstract boolean playImpl(); + protected abstract boolean resumeImpl(); @Override public final State pause(final boolean flush) { @@ -378,7 +378,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { } attributesUpdated( event_mask ); if( !pauseImpl() ) { - play(); + resume(); } } if(DEBUG) { System.err.println("Pause: "+preState+" -> "+state+", "+toString()); } @@ -388,6 +388,24 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { protected abstract boolean pauseImpl(); @Override + public final State stop() { + synchronized( stateLock ) { + final State preState = state; + if( null != streamWorker ) { + streamWorker.doStop(); + streamWorker = null; + } + resetAVPTSAndFlush(); + stopImpl(); + changeState(0, State.Uninitialized); + // attachedObjects.clear(); + if(DEBUG) { System.err.println("Stop: "+preState+" -> "+state+", "+toString()); } + return state; + } + } + protected abstract void stopImpl(); + + @Override public final State destroy(final GL gl) { return destroyImpl(gl, 0, true); } @@ -397,15 +415,17 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { streamWorker.doStopImpl(wait); streamWorker = null; } - destroyImpl(gl); + resetAVPTSAndFlush(); + destroyImpl(); removeAllTextureFrames(gl); + lastFrame = null; textureCount=0; changeState(event_mask, State.Uninitialized); attachedObjects.clear(); return state; } } - protected abstract void destroyImpl(GL gl); + protected abstract void destroyImpl(); @Override public final int seek(int msec) { @@ -534,13 +554,14 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { } @Override - public final void initStream(final Uri streamLoc, final int vid, final int aid, final int reqTextureCount) throws IllegalStateException, IllegalArgumentException { + public final void playStream(final Uri streamLoc, final int vid, final int aid, final int reqTextureCount) throws IllegalStateException, IllegalArgumentException { synchronized( stateLock ) { if(State.Uninitialized != state) { throw new IllegalStateException("Instance not in state unintialized: "+this); } if(null == streamLoc) { - throw new IllegalArgumentException("streamLock is null"); + initTestStream(); + return; } if( STREAM_ID_NONE != vid ) { textureCount = validateTextureCount(reqTextureCount); @@ -617,9 +638,9 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { @Override public final void initGL(final GL gl) throws IllegalStateException, StreamException, GLException { synchronized( stateLock ) { - if(State.Initialized != state ) { - throw new IllegalStateException("Stream not in state initialized: "+this); - } + // if(State.Initialized != state && State.Uninitialized != state) { + // throw new IllegalStateException("Stream not in state [un]initialized: "+this); + // } if( null != streamWorker ) { final StreamException streamInitErr = getStreamException(); if( null != streamInitErr ) { @@ -629,7 +650,8 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { } } try { - if( STREAM_ID_NONE != vid ) { + if( STREAM_ID_NONE != vid && State.Uninitialized != state ) { + resetAVPTSAndFlush(); removeAllTextureFrames(gl); initGLImpl(gl); if(DEBUG) { @@ -645,20 +667,40 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { videoFramesDecoded = new LFRingbuffer<TextureFrame>(TextureFrame[].class, textureCount); lastFrame = videoFramesFree.getBlocking( ); } - if( null != streamWorker ) { - streamWorker.initGL(gl); + if( null == streamWorker && + ( TEXTURE_COUNT_MIN < textureCount || STREAM_ID_NONE == vid ) ) // Enable StreamWorker for 'audio only' as well (Bug 918). + { + streamWorker = new StreamWorker(); } + streamWorker.initGL(gl); + streamWorker.doResume(); + changeState(0, State.Paused); + resume(); } else { - removeAllTextureFrames(null); - initGLImpl(null); - setTextureFormat(-1, -1); - setTextureType(-1); - videoFramesOrig = null; + resetAVPTSAndFlush(); + removeAllTextureFrames(gl); + // initGLImpl(gl); + // Using a dummy test frame + width = TestTexture.singleton.getWidth(); + height = TestTexture.singleton.getHeight(); + setTextureFormat(GL.GL_RGBA, GL.GL_RGBA); + setTextureType(GL.GL_UNSIGNED_BYTE); + textureCount = Math.max(TEXTURE_COUNT_MIN, textureCount); + videoFramesOrig = createTestTexFrames(gl, textureCount); + if( TEXTURE_COUNT_MIN == textureCount ) { + videoFramesFree = null; + videoFramesDecoded = null; + lastFrame = videoFramesOrig[0]; + } else { + videoFramesFree = new LFRingbuffer<TextureFrame>(videoFramesOrig); + videoFramesDecoded = new LFRingbuffer<TextureFrame>(TextureFrame[].class, textureCount); + lastFrame = videoFramesFree.getBlocking( ); + } videoFramesFree = null; videoFramesDecoded = null; - lastFrame = null; + lastFrame = videoFramesOrig[0]; + // changeState(0, State.Paused); } - changeState(0, State.Paused); } catch (final Throwable t) { destroyImpl(gl, GLMediaEventListener.EVENT_CHANGE_ERR, false /* wait */); // -> GLMediaPlayer.State.Uninitialized throw new GLException("Error initializing GL resources", t); @@ -703,6 +745,64 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { } return texFrames; } + protected TextureFrame[] createTestTexFrames(final GL gl, final int count) { + final int[] texNames = new int[count]; + gl.glGenTextures(count, texNames, 0); + final int err = gl.glGetError(); + if( GL.GL_NO_ERROR != err ) { + throw new RuntimeException("TextureNames creation failed (num: "+count+"): err "+toHexString(err)); + } + final TextureFrame[] texFrames = new TextureFrame[count]; + for(int i=0; i<count; i++) { + texFrames[i] = createTestTexImage(gl, texNames[i]); + } + return texFrames; + } + + private static class TestTexture { + private static final TextureData singleton; + static { + TextureData data = null; + try { + final URLConnection urlConn = IOUtil.getResource("jogamp/opengl/assets/test-ntsc01-28x16.png", NullGLMediaPlayer.class.getClassLoader()); + if(null != urlConn) { + data = TextureIO.newTextureData(GLProfile.getGL2ES2(), urlConn.getInputStream(), false, TextureIO.PNG); + } + } catch (final Exception e) { + e.printStackTrace(); + } + if(null == data) { + final int w = 28; + final int h = 16; + final ByteBuffer buffer = Buffers.newDirectByteBuffer(w*h*4); + while(buffer.hasRemaining()) { + buffer.put((byte) 0xEA); buffer.put((byte) 0xEA); buffer.put((byte) 0xEA); buffer.put((byte) 0xEA); + } + buffer.rewind(); + data = new TextureData(GLProfile.getGL2ES2(), + GL.GL_RGBA, w, h, 0, + GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, false, + false, false, buffer, null); + } + singleton = data; + } + } + private final TextureSequence.TextureFrame createTestTexImage(final GL gl, final int texName) { + final Texture texture = createTexImageImpl(gl, texName, TestTexture.singleton.getWidth(), TestTexture.singleton.getHeight()); + texture.updateImage(gl, TestTexture.singleton); + return new TextureSequence.TextureFrame( texture ); + } + private void initTestStream() { + textureCount = TEXTURE_COUNT_MIN; + final float _fps = 24f; + final int _duration = 10*60*1000; // msec + final int _totalFrames = (int) ( (_duration/1000)*_fps ); + updateAttributes(GLMediaPlayer.STREAM_ID_NONE, GLMediaPlayer.STREAM_ID_NONE, + TestTexture.singleton.getWidth(), TestTexture.singleton.getHeight(), 0, + 0, 0, _fps, + _totalFrames, 0, _duration, "png-static", null); + } + protected abstract TextureFrame createTexImage(GL gl, int texName); protected final Texture createTexImageImpl(final GL gl, final int texName, final int tWidth, final int tHeight) { @@ -763,9 +863,6 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { @Override public final TextureFrame getLastTexture() throws IllegalStateException { - if( State.Paused != state && State.Playing != state ) { - throw new IllegalStateException("Instance not paused or playing: "+this); - } return lastFrame; } @@ -774,7 +871,6 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { videoFramesOrig = null; videoFramesFree = null; videoFramesDecoded = null; - lastFrame = null; if( null != texFrames ) { for(int i=0; i<texFrames.length; i++) { final TextureFrame frame = texFrames[i]; @@ -799,9 +895,6 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { @Override public final TextureFrame getNextTexture(final GL gl) throws IllegalStateException { synchronized( stateLock ) { - if( State.Paused != state && State.Playing != state ) { - throw new IllegalStateException("Instance not paused or playing: "+this); - } if(State.Playing == state) { boolean dropFrame = false; try { @@ -857,7 +950,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { if( null == videoFramesDecoded || !videoFramesDecoded.isEmpty() ) { nullFrameCount++; } - if( DEBUG ) { + if( DEBUG_AVSYNC ) { final int audio_pts = getAudioPTSImpl(); final int audio_scr = (int) ( ( currentTimeMillis - audio_scr_t0 ) * playSpeed ); final int d_apts; @@ -897,7 +990,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { // final int d_avpts = d_vpts - d_apts; if( -VIDEO_DPTS_MAX > d_vpts || d_vpts > VIDEO_DPTS_MAX ) { // if( -VIDEO_DPTS_MAX > d_avpts || d_avpts > VIDEO_DPTS_MAX ) { - if( DEBUG ) { + if( DEBUG_AVSYNC ) { System.err.println( "AV*: dT "+(currentTimeMillis-lastTimeMillis)+", "+ getPerfStringImpl( video_scr, video_pts, d_vpts, audio_scr, audio_pts, d_apts, 0 ) + ", "+nextFrame+", playCached " + playCached+ ", dropFrame "+dropFrame); } @@ -922,7 +1015,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { dropFrame = true; } video_pts_last = video_pts; - if( DEBUG ) { + if( DEBUG_AVSYNC ) { System.err.println( "AV_: dT "+(currentTimeMillis-lastTimeMillis)+", "+ getPerfStringImpl( video_scr, video_pts, d_vpts, audio_scr, audio_pts, d_apts, @@ -1002,7 +1095,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { * {@inheritDoc} * <p> * Note: All {@link AudioSink} operations are performed from {@link GLMediaPlayerImpl}, - * i.e. {@link #play()}, {@link #pause(boolean)}, {@link #seek(int)}, {@link #setPlaySpeed(float)}, {@link #getAudioPTS()}. + * i.e. {@link #resume()}, {@link #pause(boolean)}, {@link #seek(int)}, {@link #setPlaySpeed(float)}, {@link #getAudioPTS()}. * </p> * <p> * Implementations using an {@link AudioSink} shall write it's instance to {@link #audioSink} @@ -1251,7 +1344,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { preNextTextureImpl(sharedGLCtx.getGL()); sharedGLCtxCurrent = true; } - if( null == videoFramesFree ) { + if( null == videoFramesFree && STREAM_ID_NONE != vid ) { throw new InternalError("XXX videoFramesFree is null"); } } @@ -1393,7 +1486,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { /** * Called initially by {@link #initStreamImpl(int, int)}, which - * is called off-thread by {@link #initStream(Uri, int, int, int)}. + * is called off-thread by {@link #playStream(Uri, int, int, int)}. * <p> * The latter catches an occurring exception and set the state delivers the error events. * </p> @@ -1470,11 +1563,10 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { return; } if( wasUninitialized ) { - if( null != streamWorker ) { - throw new InternalError("XXX: StreamWorker not null - "+this); - } - if( TEXTURE_COUNT_MIN < textureCount || STREAM_ID_NONE == vid ) { // Enable StreamWorker for 'audio only' as well (Bug 918). - streamWorker = new StreamWorker(); + if( null == streamWorker ) { + if( TEXTURE_COUNT_MIN < textureCount || STREAM_ID_NONE == vid ) { // Enable StreamWorker for 'audio only' as well (Bug 918). + streamWorker = new StreamWorker(); + } } if( DEBUG ) { System.err.println("XXX Initialize @ updateAttributes: "+this); diff --git a/src/jogl/classes/jogamp/opengl/util/av/NullGLMediaPlayer.java b/src/jogl/classes/jogamp/opengl/util/av/NullGLMediaPlayer.java index 59dba68f2..528b62db6 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/NullGLMediaPlayer.java +++ b/src/jogl/classes/jogamp/opengl/util/av/NullGLMediaPlayer.java @@ -66,7 +66,7 @@ public class NullGLMediaPlayer extends GLMediaPlayerImpl { } @Override - protected final boolean playImpl() { + protected final boolean resumeImpl() { pos_start = Platform.currentTimeMillis(); return true; } @@ -77,6 +77,10 @@ public class NullGLMediaPlayer extends GLMediaPlayerImpl { } @Override + protected final void stopImpl() { + } + + @Override protected final int seekImpl(final int msec) { pos_ms = msec; validatePos(); @@ -98,7 +102,7 @@ public class NullGLMediaPlayer extends GLMediaPlayerImpl { } @Override - protected final void destroyImpl(final GL gl) { + protected final void destroyImpl() { if(null != texData) { texData.destroy(); texData = null; 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 aae1d75d0..91bef005a 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java +++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java @@ -297,16 +297,19 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl { if(!available) { throw new RuntimeException("FFMPEGMediaPlayer not available"); } + psm = new GLPixelStorageModes(); + initSelf(); + } + private void initSelf() { moviePtr = natives.createInstance0(this, DEBUG_NATIVE); if(0==moviePtr) { throw new GLException("Couldn't create FFMPEGInstance"); } - psm = new GLPixelStorageModes(); audioSink = null; } @Override - protected final void destroyImpl(final GL gl) { + protected final void destroyImpl() { if (moviePtr != 0) { natives.destroyInstance0(moviePtr); moviePtr = 0; @@ -321,6 +324,12 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl { } } + @Override + protected void stopImpl() { + destroyImpl(); + initSelf(); + } + public static final String dev_video_linux = "/dev/video"; @Override @@ -394,9 +403,6 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl { if(0==moviePtr) { throw new GLException("FFMPEG native instance null"); } - if(null == audioSink) { - throw new GLException("AudioSink null"); - } final int audioQueueLimit; if( null != gl && STREAM_ID_NONE != getVID() ) { final GLContextImpl ctx = (GLContextImpl)gl.getContext(); @@ -419,8 +425,10 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl { System.err.println("initGL: p3 avChosen "+avChosenAudioFormat); } - if( STREAM_ID_NONE == getAID() ) { - audioSink.destroy(); + if( STREAM_ID_NONE == getAID() || null == audioSink ) { + if(null != audioSink) { + audioSink.destroy(); + } audioSink = AudioSinkFactory.createNull(); audioSink.init(AudioSink.DefaultFormat, 0, AudioSink.DefaultInitialQueueSize, AudioSink.DefaultQueueGrowAmount, audioQueueLimit); } else { @@ -475,6 +483,7 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl { } setTextureFormat(tif, tf); setTextureType(tt); + setIsGLOriented(false); if(DEBUG) { System.err.println("initGL: p5: video "+vPixelFmt+", planes "+vPlanes+", bpp "+vBitsPerPixel+"/"+vBytesPerPixelPerPlane+ ", tex "+texWidth+"x"+texHeight+", usesTexLookupShader "+usesTexLookupShader); @@ -694,10 +703,7 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl { * Otherwise the call is delegated to it's super class. */ @Override - public final String getTextureLookupFunctionName(final String desiredFuncName) throws IllegalStateException { - if( State.Uninitialized == getState() ) { - throw new IllegalStateException("Instance not initialized: "+this); - } + public final String getTextureLookupFunctionName(final String desiredFuncName) { if( usesTexLookupShader ) { if(null != desiredFuncName && desiredFuncName.length()>0) { texLookupFuncName = desiredFuncName; @@ -714,10 +720,7 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl { * e.g. YUV420P to RGB. Otherwise the call is delegated to it's super class. */ @Override - public final String getTextureLookupFragmentShaderImpl() throws IllegalStateException { - if( State.Uninitialized == getState() ) { - throw new IllegalStateException("Instance not initialized: "+this); - } + public final String getTextureLookupFragmentShaderImpl() { if( !usesTexLookupShader ) { return super.getTextureLookupFragmentShaderImpl(); } @@ -825,7 +828,7 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl { } @Override - public final boolean playImpl() { + public final boolean resumeImpl() { if(0==moviePtr) { return false; } diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java b/src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java index c69108b04..336084734 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java +++ b/src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java @@ -86,7 +86,7 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl { } @Override - protected void destroyImpl(final GL gl) { + protected void destroyImpl() { if (moviePtr != 0) { _stop(moviePtr); _detachVideoRenderer(moviePtr); @@ -137,7 +137,7 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl { } @Override - public synchronized boolean playImpl() { + public synchronized boolean resumeImpl() { if(0==moviePtr) { return false; } @@ -155,6 +155,12 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl { return true; } + @Override + protected final void stopImpl() { + destroyImpl(); + initOMX(); + } + /** @return time position after issuing the command */ @Override protected int seekImpl(final int msec) { diff --git a/src/jogl/native/libav/ffmpeg_impl_template.c b/src/jogl/native/libav/ffmpeg_impl_template.c index 76addd9ad..ee91abe5e 100644 --- a/src/jogl/native/libav/ffmpeg_impl_template.c +++ b/src/jogl/native/libav/ffmpeg_impl_template.c @@ -363,6 +363,7 @@ static void freeInstance(JNIEnv *env, FFMPEGToolBasicAV_t* pAV) { int i; if(NULL != pAV) { MY_MUTEX_LOCK(env, mutex_avcodec_openclose); + pAV->ready = 0; { // Close the V codec if(NULL != pAV->pVCodecCtx) { @@ -509,6 +510,7 @@ JNIEXPORT jlong JNICALL FF_FUNC(createInstance0) JoglCommon_throwNewRuntimeException(env, "Couldn't alloc instance"); return 0; } + pAV->ready = 0; pAV->avcodecVersion = sp_avcodec_version(); pAV->avformatVersion = sp_avformat_version(); pAV->avutilVersion = sp_avutil_version(); @@ -1173,6 +1175,7 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0) initPTSStats(&pAV->vPTSStats); initPTSStats(&pAV->aPTSStats); _updateJavaAttributes(env, pAV); + pAV->ready = 1; } JNIEXPORT void JNICALL FF_FUNC(setGLFuncs0) @@ -1197,6 +1200,9 @@ JNIEXPORT jint JNICALL FF_FUNC(readNextPacket0) (JNIEnv *env, jobject instance, jlong ptr, jint texTarget, jint texFmt, jint texType) { FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr)); + if( 0 == pAV->ready ) { + return 0; + } jint resPTS = INVALID_PTS; uint8_t * pkt_odata; @@ -1556,12 +1562,18 @@ JNIEXPORT jint JNICALL FF_FUNC(play0) (JNIEnv *env, jobject instance, jlong ptr) { FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr)); + if( 0 == pAV->ready ) { + return 0; + } return sp_av_read_play(pAV->pFormatCtx); } JNIEXPORT jint JNICALL FF_FUNC(pause0) (JNIEnv *env, jobject instance, jlong ptr) { FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr)); + if( 0 == pAV->ready ) { + return 0; + } return sp_av_read_pause(pAV->pFormatCtx); } @@ -1569,6 +1581,9 @@ JNIEXPORT jint JNICALL FF_FUNC(seek0) (JNIEnv *env, jobject instance, jlong ptr, jint pos1) { const FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr)); + if( 0 == pAV->ready ) { + return 0; + } int64_t pos0, pts0; int streamID; AVRational time_base; @@ -1627,6 +1642,9 @@ JNIEXPORT jint JNICALL FF_FUNC(getVideoPTS0) (JNIEnv *env, jobject instance, jlong ptr) { FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr)); + if( 0 == pAV->ready ) { + return 0; + } return pAV->vPTS; } @@ -1634,6 +1652,9 @@ JNIEXPORT jint JNICALL FF_FUNC(getAudioPTS0) (JNIEnv *env, jobject instance, jlong ptr) { FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr)); + if( 0 == pAV->ready ) { + return 0; + } return pAV->aPTS; } diff --git a/src/jogl/native/libav/ffmpeg_tool.h b/src/jogl/native/libav/ffmpeg_tool.h index dd39146e6..02a297f73 100644 --- a/src/jogl/native/libav/ffmpeg_tool.h +++ b/src/jogl/native/libav/ffmpeg_tool.h @@ -202,6 +202,8 @@ typedef struct { char acodec[64]; char vcodec[64]; + int32_t ready; + } FFMPEGToolBasicAV_t ; #endif /* _FFMPEG_TOOL_H */ |