diff options
17 files changed, 373 insertions, 340 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/av/GLMediaEventListener.java b/src/jogl/classes/com/jogamp/opengl/av/GLMediaEventListener.java index a02c8a362..9887a417c 100644 --- a/src/jogl/classes/com/jogamp/opengl/av/GLMediaEventListener.java +++ b/src/jogl/classes/com/jogamp/opengl/av/GLMediaEventListener.java @@ -1,7 +1,7 @@ package com.jogamp.opengl.av; -import com.jogamp.opengl.av.GLMediaPlayer.TextureFrame; +import javax.media.opengl.GL; public interface GLMediaEventListener { @@ -10,8 +10,19 @@ public interface GLMediaEventListener { static final int EVENT_CHANGE_BPS = 1<<2; static final int EVENT_CHANGE_LENGTH = 1<<3; - public void attributesChanges(GLMediaPlayer mp, int event_mask); - public void newFrameAvailable(GLMediaPlayer mp, TextureFrame frame); + /** + * @param mp the event source + * @param event_mask the changes attributes + * @param when system time in msec. + */ + public void attributesChanges(GLMediaPlayer mp, int event_mask, long when); + + /** + * Signaling listeners that {@link GLMediaPlayer#getNextTexture(GL, boolean)} is able to deliver a new frame. + * @param mp the event source + * @param when system time in msec. + **/ + public void newFrameAvailable(GLMediaPlayer mp, long when); } diff --git a/src/jogl/classes/com/jogamp/opengl/av/GLMediaPlayer.java b/src/jogl/classes/com/jogamp/opengl/av/GLMediaPlayer.java index e5f69b6de..b3827d520 100644 --- a/src/jogl/classes/com/jogamp/opengl/av/GLMediaPlayer.java +++ b/src/jogl/classes/com/jogamp/opengl/av/GLMediaPlayer.java @@ -36,24 +36,24 @@ import javax.media.opengl.GLException; import jogamp.opengl.Debug; import com.jogamp.opengl.util.texture.Texture; +import com.jogamp.opengl.util.texture.TextureCoords; /** * Lifecycle of an GLMediaPlayer: * <table border="1"> - * <tr><th>action</th> <th>state before</th> <th>state after</th></tr> - * <tr><td>{@link #initStream(URLConnection)}</td> <td>UninitializedStream</td> <td>UninitializedGL</td></tr> - * <tr><td>{@link #initGL(GL)}</td> <td>UninitializedGL</td> <td>Stopped</td></tr> - * <tr><td>{@link #start()}</td> <td>Stopped, Paused</td> <td>Playing</td></tr> - * <tr><td>{@link #stop()}</td> <td>Playing, Paused</td> <td>Stopped</td></tr> - * <tr><td>{@link #pause()}</td> <td>Playing</td> <td>Paused</td></tr> - * <tr><td>{@link #destroy(GL)}</td> <td>ANY</td> <td>UninitializedStream</td></tr> + * <tr><th>action</th> <th>state before</th> <th>state after</th></tr> + * <tr><td>{@link #initGLStream(GL, URLConnection)}</td> <td>Uninitialized</td> <td>Stopped</td></tr> + * <tr><td>{@link #start()}</td> <td>Stopped, Paused</td> <td>Playing</td></tr> + * <tr><td>{@link #stop()}</td> <td>Playing, Paused</td> <td>Stopped</td></tr> + * <tr><td>{@link #pause()}</td> <td>Playing</td> <td>Paused</td></tr> + * <tr><td>{@link #destroy(GL)}</td> <td>ANY</td> <td>Uninitialized</td></tr> * </table> */ public interface GLMediaPlayer { public static final boolean DEBUG = Debug.debug("GLMediaPlayer"); public enum State { - UninitializedStream(0), UninitializedGL(1), Stopped(2), Playing(3), Paused(4); + Uninitialized(0), Stopped(1), Playing(2), Paused(3); public final int id; @@ -83,6 +83,10 @@ public interface GLMediaPlayer { public int getTextureTarget(); + /** Defaults to 0 */ + public void setTextureUnit(int u); + public int getTextureUnit(); + /** Sets the texture min-mag filter, defaults to {@link GL#GL_NEAREST}. */ public void setTextureMinMagFilter(int[] minMagFilter); public int[] getTextureMinMagFilter(); @@ -92,24 +96,20 @@ public interface GLMediaPlayer { public int[] getTextureWrapST(); /** - * Sets the stream to be used. Initializes all stream related states. + * Sets the stream to be used. Initializes all stream related states inclusive OpenGL ones, + * if <code>gl</code> is not null. * <p> - * UninitializedStream -> UninitializedGL + * Uninitialized -> Stopped * </p> + * @param gl current GL object. If null, no video output and textures will be available. + * @param urlConn the stream connection + * @return the new state + * + * @throws IllegalStateException if not invoked in state Uninitialized * @throws IOException in case of difficulties to open or process the stream - * @throws IllegalStateException if not invoked in state UninitializedStream - */ - public State initStream(URLConnection urlConn) throws IllegalStateException, IOException; - - /** - * Initializes all GL related resources. - * <p> - * UninitializedGL -> Stopped - * </p> * @throws GLException in case of difficulties to initialize the GL resources - * @throws IllegalStateException if not invoked in state UninitializedGL */ - public State initGL(GL gl) throws IllegalStateException, GLException; + public State initGLStream(GL gl, URLConnection urlConn) throws IllegalStateException, GLException, IOException; /** * Releases the GL and stream resources. @@ -157,17 +157,27 @@ public interface GLMediaPlayer { public long seek(long msec); /** - * @return the last updated texture. Not blocking. + * @return the last updated texture. Maybe <code>null</code> in case no last frame is available. + * Not blocking. */ public TextureFrame getLastTexture(); /** - * @return the next texture, which should be rendered. May block, depending on implementation. + * Returns the next texture to be rendered. + * <p> + * Implementation shall block until next frame is available if <code>blocking</code> is <code>true</code>, + * otherwise it shall return the last frame in case a new frame is not available. + * </p> + * <p> + * Shall return <code>null</code> in case <i>no</i> frame is available. + * </p> * * @see #addEventListener(GLMediaEventListener) - * @see GLMediaEventListener#newFrameAvailable(GLMediaPlayer, TextureFrame) + * @see GLMediaEventListener#newFrameAvailable(GLMediaPlayer, long) */ - public TextureFrame getNextTexture(); + public TextureFrame getNextTexture(GL gl, boolean blocking); + + public TextureCoords getTextureCoords(); public URLConnection getURLConnection(); diff --git a/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java b/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java index 7e94d3cc5..ae45662db 100644 --- a/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java +++ b/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java @@ -30,9 +30,10 @@ package jogamp.opengl.android.av; import java.io.IOException; import javax.media.opengl.GL; -import javax.media.opengl.GLContext; import javax.media.opengl.GLES2; +import com.jogamp.opengl.util.texture.TextureCoords; + import jogamp.common.os.android.StaticContext; import jogamp.opengl.av.GLMediaPlayerImpl; @@ -42,31 +43,21 @@ import android.media.MediaPlayer; import android.net.Uri; import android.view.Surface; -import com.jogamp.opengl.util.texture.Texture; - /*** * Android API Level 14: {@link MediaPlayer#setSurface(Surface)} * Android API Level 14: {@link Surface#Surface(android.graphics.SurfaceTexture)} */ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl { MediaPlayer mp; - boolean updateSurface = false; + volatile boolean updateSurface = false; Object updateSurfaceLock = new Object(); - AndroidTextureFrame atex = null; - - public static class AndroidTextureFrame extends TextureFrame { - public AndroidTextureFrame(Texture t, SurfaceTexture stex) { - super(t); - this.stex = stex; - } - - public final SurfaceTexture getSurfaceTexture() { return stex; } - - public String toString() { - return "AndroidTextureFrame[" + texture + ", "+ stex + "]"; - } - protected SurfaceTexture stex; - } + TextureFrame lastTexFrame = null; + + /** + private static String toString(MediaPlayer m) { + if(null == m) return "<nil>"; + return "MediaPlayer[playing "+m.isPlaying()+", pos "+m.getCurrentPosition()/1000.0f+"s, "+m.getVideoWidth()+"x"+m.getVideoHeight()+"]"; + } */ public AndroidGLMediaPlayerAPI14() { super(); @@ -103,6 +94,7 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl { @Override protected boolean pauseImpl() { if(null != mp) { + wakeUp(false); try { mp.pause(); return true; @@ -118,6 +110,7 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl { @Override protected boolean stopImpl() { if(null != mp) { + wakeUp(false); try { mp.stop(); return true; @@ -141,24 +134,49 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl { @Override public TextureFrame getLastTexture() { - return atex; + return lastTexFrame; } @Override - public TextureFrame getNextTexture() { - if(null != atex && null != mp) { - final boolean _updateSurface; - synchronized(updateSurfaceLock) { - _updateSurface = updateSurface; - updateSurface = false; + public TextureFrame getNextTexture(GL gl, boolean blocking) { + if(null != stex && null != mp) { + // Only block once, no while-loop. + // This relaxes locking code of non crucial resources/events. + boolean update = updateSurface; + if(!update && blocking) { + synchronized(updateSurfaceLock) { + if(!updateSurface) { // volatile OK. + try { + updateSurfaceLock.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + updateSurface = false; + update = true; + } } - if(_updateSurface) { - atex.getSurfaceTexture().updateTexImage(); - // atex.getSurfaceTexture().getTransformMatrix(atex.getSTMatrix()); + if(update) { + stex.updateTexImage(); + // stex.getTransformMatrix(atex.getSTMatrix()); + lastTexFrame=texFrames[0]; } - return atex; - } else { - return null; + + } + return lastTexFrame; + } + + @Override + public TextureCoords getTextureCoords() { + return texFrames[0].getTexture().getImageTexCoords(); + } + + private void wakeUp(boolean newFrame) { + synchronized(updateSurfaceLock) { + if(newFrame) { + updateSurface = true; + } + updateSurfaceLock.notifyAll(); } } @@ -170,13 +188,16 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl { @Override protected void destroyImpl(GL gl) { if(null != mp) { + wakeUp(false); mp.release(); mp = null; } } + SurfaceTexture stex = null; + @Override - protected void initStreamImplPreGL() throws IOException { + protected void initGLStreamImpl(GL gl, int[] texNames) throws IOException { if(null!=mp && null!=urlConn) { try { final Uri uri = Uri.parse(urlConn.getURL().toExternalForm()); @@ -188,12 +209,16 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl { } catch (IllegalStateException e) { throw new RuntimeException(e); } + stex = new SurfaceTexture(texNames[0]); // only 1 texture + stex.setOnFrameAvailableListener(onFrameAvailableListener); + final Surface surf = new Surface(stex); + mp.setSurface(surf); + surf.release(); try { mp.prepare(); } catch (IOException ioe) { throw new IOException("MediaPlayer failed to process stream <"+urlConn.getURL().toExternalForm()+">: "+ioe.getMessage(), ioe); } - width = mp.getVideoWidth(); height = mp.getVideoHeight(); fps = 0; @@ -206,34 +231,20 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl { } @Override - protected void destroyTexImage(GLContext ctx, TextureFrame imgTex) { - final AndroidTextureFrame atf = (AndroidTextureFrame) imgTex; - atf.getSurfaceTexture().release(); - atex = null; - super.destroyTexImage(ctx, imgTex); + protected void destroyTexImage(GL gl, TextureFrame imgTex) { + if(null != stex) { + stex.release(); + stex = null; + } + lastTexFrame = null; + super.destroyTexImage(gl, imgTex); } - @Override - protected TextureFrame createTexImage(GLContext ctx, int idx, int[] tex) { - final Texture texture = super.createTexImageImpl(ctx, idx, tex, true); - - final SurfaceTexture stex = new SurfaceTexture(tex[idx]); - stex.setOnFrameAvailableListener(onFrameAvailableListener); - final Surface surf = new Surface(stex); - mp.setSurface(surf); - surf.release(); - - atex = new AndroidTextureFrame( texture, stex ); - return atex; - } - protected OnFrameAvailableListener onFrameAvailableListener = new OnFrameAvailableListener() { @Override public void onFrameAvailable(SurfaceTexture surfaceTexture) { - synchronized(updateSurfaceLock) { - updateSurface = true; - } - AndroidGLMediaPlayerAPI14.this.newFrameAvailable(atex); + wakeUp(true); + AndroidGLMediaPlayerAPI14.this.newFrameAvailable(); } }; } diff --git a/src/jogl/classes/jogamp/opengl/av/EGLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/av/EGLMediaPlayerImpl.java index abc5d5912..2f6744fc5 100644 --- a/src/jogl/classes/jogamp/opengl/av/EGLMediaPlayerImpl.java +++ b/src/jogl/classes/jogamp/opengl/av/EGLMediaPlayerImpl.java @@ -27,8 +27,11 @@ */ package jogamp.opengl.av; -import javax.media.opengl.GLContext; +import java.nio.IntBuffer; +import javax.media.opengl.GL; + +import com.jogamp.common.nio.Buffers; import com.jogamp.opengl.util.texture.Texture; import jogamp.opengl.egl.EGL; @@ -80,22 +83,23 @@ public abstract class EGLMediaPlayerImpl extends GLMediaPlayerImpl { } @Override - protected TextureFrame createTexImage(GLContext ctx, int idx, int[] tex) { - final Texture texture = super.createTexImageImpl(ctx, idx, tex, true); + protected TextureFrame createTexImage(GL gl, int idx, int[] tex) { + final Texture texture = super.createTexImageImpl(gl, idx, tex, true); final long image; final long sync; - final EGLContext eglCtx = (EGLContext) ctx; + final EGLContext eglCtx = (EGLContext) gl.getContext(); final EGLExt eglExt = eglCtx.getEGLExt(); final EGLDrawable eglDrawable = (EGLDrawable) eglCtx.getGLDrawable(); int[] tmp = new int[1]; + IntBuffer nioTmp = Buffers.newDirectIntBuffer(1); if(TextureType.KHRImage == texType) { // create EGLImage from texture - tmp[0] = EGL.EGL_NONE; + nioTmp.put(0, EGL.EGL_NONE); image = eglExt.eglCreateImageKHR( eglDrawable.getDisplay(), eglCtx.getHandle(), EGLExt.EGL_GL_TEXTURE_2D_KHR, - tex[idx], tmp, 0); + null /* buffer */, nioTmp); if (0==image) { throw new RuntimeException("EGLImage creation failed: "+EGL.eglGetError()+", ctx "+eglCtx+", tex "+tex[idx]+", err "+toHexString(EGL.eglGetError())); } @@ -119,8 +123,8 @@ public abstract class EGLMediaPlayerImpl extends GLMediaPlayerImpl { } @Override - protected void destroyTexImage(GLContext ctx, TextureFrame imgTex) { - final EGLContext eglCtx = (EGLContext) ctx; + protected void destroyTexImage(GL gl, TextureFrame imgTex) { + final EGLContext eglCtx = (EGLContext) gl.getContext(); final EGLExt eglExt = eglCtx.getEGLExt(); final EGLDrawable eglDrawable = (EGLDrawable) eglCtx.getGLDrawable(); final EGLTextureFrame eglTex = (EGLTextureFrame) imgTex; @@ -131,6 +135,6 @@ public abstract class EGLMediaPlayerImpl extends GLMediaPlayerImpl { if(0!=eglTex.getSync()) { eglExt.eglDestroySyncKHR(eglDrawable.getDisplay(), eglTex.getSync()); } - super.destroyTexImage(ctx, imgTex); + super.destroyTexImage(gl, imgTex); } } diff --git a/src/jogl/classes/jogamp/opengl/av/GLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/av/GLMediaPlayerImpl.java index f6fc20afe..acd707288 100644 --- a/src/jogl/classes/jogamp/opengl/av/GLMediaPlayerImpl.java +++ b/src/jogl/classes/jogamp/opengl/av/GLMediaPlayerImpl.java @@ -34,7 +34,6 @@ import java.util.HashMap; import java.util.Iterator; import javax.media.opengl.GL; -import javax.media.opengl.GLContext; import javax.media.opengl.GLES2; import javax.media.opengl.GLException; @@ -59,6 +58,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { protected State state; protected int textureCount; protected int textureTarget; + protected int texUnit; protected int[] texMinMagFilter = { GL.GL_NEAREST, GL.GL_NEAREST }; protected int[] texWrapST = { GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE }; @@ -67,35 +67,39 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { protected float playSpeed = 1.0f; - /** Shall be set by the {@link #initStreamImplPreGL()} method implementation. */ + /** Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */ protected int width = 0; - /** Shall be set by the {@link #initStreamImplPreGL()} method implementation. */ + /** Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */ protected int height = 0; - /** Shall be set by the {@link #initStreamImplPreGL()} method implementation. */ + /** Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */ protected int fps = 0; - /** Shall be set by the {@link #initStreamImplPreGL()} method implementation. */ + /** Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */ protected long bps = 0; - /** In frames. Shall be set by the {@link #initStreamImplPreGL()} method implementation. */ + /** In frames. Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */ protected long totalFrames = 0; - /** In ms. Shall be set by the {@link #initStreamImplPreGL()} method implementation. */ + /** In ms. Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */ protected long duration = 0; - /** Shall be set by the {@link #initStreamImplPreGL()} method implementation. */ + /** Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */ protected String acodec = null; - /** Shall be set by the {@link #initStreamImplPreGL()} method implementation. */ + /** Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */ protected String vcodec = null; protected long frameNumber = 0; - private TextureFrame[] texFrames = null; + protected TextureFrame[] texFrames = null; protected HashMap<Integer, TextureFrame> texFrameMap = new HashMap<Integer, TextureFrame>(); private ArrayList<GLMediaEventListener> eventListeners = new ArrayList<GLMediaEventListener>(); protected GLMediaPlayerImpl() { this.textureCount=3; this.textureTarget=GL.GL_TEXTURE_2D; - this.state = State.UninitializedStream; + this.texUnit = 0; + this.state = State.Uninitialized; } + public void setTextureUnit(int u) { texUnit = u; } + public int getTextureUnit() { return texUnit; } + protected final void setTextureCount(int textureCount) { this.textureCount=textureCount; } @@ -162,20 +166,47 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { public final State getState() { return state; } @Override - public final State initStream(URLConnection urlConn) throws IllegalStateException, IOException { - if(State.UninitializedStream != state) { - throw new IllegalStateException("Instance not in state "+State.UninitializedStream+", but "+state+", "+this); + public State initGLStream(GL gl, URLConnection urlConn) throws IllegalStateException, GLException, IOException { + if(State.Uninitialized != state) { + throw new IllegalStateException("Instance not in state "+State.Uninitialized+", but "+state+", "+this); } this.urlConn = urlConn; if (this.urlConn != null) { - initStreamImplPreGL(); - state = State.UninitializedGL; + try { + if(null!=texFrames) { + removeAllImageTextures(gl); + } else { + texFrames = new TextureFrame[textureCount]; + } + + final int[] tex = new int[textureCount]; + { + gl.glGenTextures(textureCount, tex, 0); + final int err = gl.glGetError(); + if( GL.GL_NO_ERROR != err ) { + throw new RuntimeException("TextureNames creation failed (num: "+textureCount+"): err "+toHexString(err)); + } + } + initGLStreamImpl(gl, tex); + + for(int i=0; i<textureCount; i++) { + final TextureFrame tf = createTexImage(gl, i, tex); + texFrames[i] = tf; + texFrameMap.put(tex[i], tf); + } + state = State.Stopped; + return state; + } catch (Throwable t) { + throw new GLException("Error initializing GL resources", t); + } } - return state; + return state; } /** - * Implementation shall set the following set of data here or at {@link #setStreamImplPostGL()} + * Implementation shall set the following set of data here + * @param gl TODO + * @param texNames TODO * @see #width * @see #height * @see #fps @@ -184,52 +215,13 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { * @see #acodec * @see #vcodec */ - protected abstract void initStreamImplPreGL() throws IOException; - - @Override - public final State initGL(GL gl) throws IllegalStateException, GLException { - if(State.UninitializedGL != state) { - throw new IllegalStateException("Instance not in state "+State.UninitializedGL+", but "+state+", "+this); - } - final GLContext ctx = gl.getContext(); - if(!ctx.isCurrent()) { - throw new GLException("Not current: "+ctx); - } + protected abstract void initGLStreamImpl(GL gl, int[] texNames) throws IOException; - try { - if(null!=texFrames) { - removeAllImageTextures(ctx); - } else { - texFrames = new TextureFrame[textureCount]; - } - - final int[] tex = new int[textureCount]; - { - gl.glGenTextures(textureCount, tex, 0); - final int err = gl.glGetError(); - if( GL.GL_NO_ERROR != err ) { - throw new RuntimeException("TextureNames creation failed (num: "+textureCount+"): err "+toHexString(err)); - } - } - - for(int i=0; i<textureCount; i++) { - final TextureFrame tf = createTexImage(ctx, i, tex); - texFrames[i] = tf; - texFrameMap.put(tex[i], tf); - } - state = State.Stopped; - return state; - } catch (Throwable t) { - throw new GLException("Error initializing GL resources", t); - } - } - - protected TextureFrame createTexImage(GLContext ctx, int idx, int[] tex) { - return new TextureFrame( createTexImageImpl(ctx, idx, tex, true) ); + protected TextureFrame createTexImage(GL gl, int idx, int[] tex) { + return new TextureFrame( createTexImageImpl(gl, idx, tex, true) ); } - protected Texture createTexImageImpl(GLContext ctx, int idx, int[] tex, boolean mustFlipVertically) { - final GL gl = ctx.getGL(); + protected Texture createTexImageImpl(GL gl, int idx, int[] tex, boolean mustFlipVertically) { if( 0 > tex[idx] ) { throw new RuntimeException("TextureName "+toHexString(tex[idx])+" invalid."); } @@ -272,16 +264,16 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { mustFlipVertically); } - protected void destroyTexImage(GLContext ctx, TextureFrame imgTex) { - imgTex.getTexture().destroy(ctx.getGL()); + protected void destroyTexImage(GL gl, TextureFrame imgTex) { + imgTex.getTexture().destroy(gl); } - protected void removeAllImageTextures(GLContext ctx) { + protected void removeAllImageTextures(GL gl) { if(null != texFrames) { for(int i=0; i<textureCount; i++) { final TextureFrame imgTex = texFrames[i]; if(null != imgTex) { - destroyTexImage(ctx, imgTex); + destroyTexImage(gl, imgTex); texFrames[i] = null; } } @@ -292,15 +284,15 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { protected void attributesUpdated(int event_mask) { synchronized(eventListenersLock) { for(Iterator<GLMediaEventListener> i = eventListeners.iterator(); i.hasNext(); ) { - i.next().attributesChanges(this, event_mask); + i.next().attributesChanges(this, event_mask, System.currentTimeMillis()); } } } - protected void newFrameAvailable(TextureFrame frame) { + protected void newFrameAvailable() { frameNumber++; synchronized(eventListenersLock) { for(Iterator<GLMediaEventListener> i = eventListeners.iterator(); i.hasNext(); ) { - i.next().newFrameAvailable(this, frame); + i.next().newFrameAvailable(this, System.currentTimeMillis()); } } } @@ -313,8 +305,8 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { @Override public synchronized State destroy(GL gl) { destroyImpl(gl); - removeAllImageTextures(gl.getContext()); - state = State.UninitializedStream; + removeAllImageTextures(gl); + state = State.Uninitialized; return state; } protected abstract void destroyImpl(GL gl); @@ -367,7 +359,8 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { @Override public synchronized String toString() { final float ct = getCurrentPosition() / 1000.0f, tt = getDuration() / 1000.0f; - return "GLMediaPlayer ["+state+", "+frameNumber+"/"+totalFrames+" frames, "+ct+"/"+tt+"s, stream [video ["+vcodec+", "+width+"x"+height+", "+fps+"fps, "+bps+"bsp], "+urlConn.getURL().toExternalForm()+"]]"; + final String loc = ( null != urlConn ) ? urlConn.getURL().toExternalForm() : "<undefined stream>" ; + return "GLMediaPlayer ["+state+", "+frameNumber+"/"+totalFrames+" frames, "+ct+"/"+tt+"s, stream [video ["+vcodec+", "+width+"x"+height+", "+fps+"fps, "+bps+"bsp], "+loc+"]]"; } @Override diff --git a/src/jogl/classes/jogamp/opengl/av/NullGLMediaPlayer.java b/src/jogl/classes/jogamp/opengl/av/NullGLMediaPlayer.java index c7eb2722c..a5d41bc9c 100644 --- a/src/jogl/classes/jogamp/opengl/av/NullGLMediaPlayer.java +++ b/src/jogl/classes/jogamp/opengl/av/NullGLMediaPlayer.java @@ -32,7 +32,6 @@ import java.net.URLConnection; import java.nio.ByteBuffer; import javax.media.opengl.GL; -import javax.media.opengl.GLContext; import javax.media.opengl.GLProfile; import jogamp.opengl.av.GLMediaPlayerImpl; @@ -40,6 +39,7 @@ import jogamp.opengl.av.GLMediaPlayerImpl; import com.jogamp.common.nio.Buffers; import com.jogamp.common.util.IOUtil; import com.jogamp.opengl.util.texture.Texture; +import com.jogamp.opengl.util.texture.TextureCoords; import com.jogamp.opengl.util.texture.TextureData; import com.jogamp.opengl.util.texture.TextureIO; @@ -96,11 +96,16 @@ public class NullGLMediaPlayer extends GLMediaPlayerImpl { } @Override - public TextureFrame getNextTexture() { + public TextureFrame getNextTexture(GL gl, boolean blocking) { return frame; } @Override + public TextureCoords getTextureCoords() { + return frame.getTexture().getImageTexCoords(); + } + + @Override public long getCurrentPosition() { pos_ms = System.currentTimeMillis() - pos_start; validatePos(); @@ -112,7 +117,7 @@ public class NullGLMediaPlayer extends GLMediaPlayerImpl { } @Override - protected void initStreamImplPreGL() throws IOException { + protected void initGLStreamImpl(GL gl, int[] texNames) throws IOException { try { URLConnection urlConn = IOUtil.getResource("jogl/util/data/av/test-ntsc01-160x90.png", NullGLMediaPlayer.class.getClassLoader()); if(null != urlConn) { @@ -146,15 +151,15 @@ public class NullGLMediaPlayer extends GLMediaPlayerImpl { } @Override - protected void destroyTexImage(GLContext ctx, TextureFrame imgTex) { - super.destroyTexImage(ctx, imgTex); + protected void destroyTexImage(GL gl, TextureFrame imgTex) { + super.destroyTexImage(gl, imgTex); } @Override - protected TextureFrame createTexImage(GLContext ctx, int idx, int[] tex) { - Texture texture = super.createTexImageImpl(ctx, idx, tex, false); + protected TextureFrame createTexImage(GL gl, int idx, int[] tex) { + Texture texture = super.createTexImageImpl(gl, idx, tex, false); if(null != texData) { - texture.updateImage(ctx.getGL(), texData); + texture.updateImage(gl, texData); } frame = new TextureFrame( texture ); return frame; diff --git a/src/jogl/classes/jogamp/opengl/omx/OMXGLMediaPlayer.java b/src/jogl/classes/jogamp/opengl/omx/OMXGLMediaPlayer.java index 99639ae62..7c775dd9f 100644 --- a/src/jogl/classes/jogamp/opengl/omx/OMXGLMediaPlayer.java +++ b/src/jogl/classes/jogamp/opengl/omx/OMXGLMediaPlayer.java @@ -5,10 +5,10 @@ import java.io.IOException; import java.net.URL; import javax.media.opengl.GL; -import javax.media.opengl.GLContext; import javax.media.opengl.GLException; import com.jogamp.opengl.av.GLMediaEventListener; +import com.jogamp.opengl.util.texture.TextureCoords; import jogamp.opengl.av.EGLMediaPlayerImpl; import jogamp.opengl.egl.EGL; @@ -41,16 +41,16 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl { } @Override - protected TextureFrame createTexImage(GLContext ctx, int idx, int[] tex) { - final EGLTextureFrame eglTex = (EGLTextureFrame) super.createTexImage(ctx, idx, tex); + protected TextureFrame createTexImage(GL gl, int idx, int[] tex) { + final EGLTextureFrame eglTex = (EGLTextureFrame) super.createTexImage(gl, idx, tex); _setStreamEGLImageTexture2D(moviePtr, idx, tex[idx], eglTex.getImage(), eglTex.getSync()); lastTex = eglTex; return eglTex; } @Override - protected void destroyTexImage(GLContext ctx, TextureFrame imgTex) { - super.destroyTexImage(ctx, imgTex); + protected void destroyTexImage(GL gl, TextureFrame imgTex) { + super.destroyTexImage(gl, imgTex); } @Override @@ -63,7 +63,7 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl { } @Override - protected void initStreamImplPreGL() throws IOException { + protected void initGLStreamImpl(GL gl, int[] texNames) throws IOException { if(0==moviePtr) { throw new GLException("OMX native instance null"); } @@ -140,17 +140,25 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl { } @Override - public synchronized TextureFrame getNextTexture() { + public synchronized TextureFrame getNextTexture(GL gl, boolean blocking) { if(0==moviePtr) { throw new GLException("OMX native instance null"); } - lastTex=null; - TextureFrame eglImgTex = texFrameMap.get(new Integer(_getNextTextureID(moviePtr))); - if(null!=eglImgTex) { - lastTex = eglImgTex; + final int nextTex = _getNextTextureID(moviePtr, blocking); + if(0 < nextTex) { + final TextureFrame eglImgTex = texFrameMap.get(new Integer(_getNextTextureID(moviePtr, blocking))); + if(null!=eglImgTex) { + lastTex = eglImgTex; + } } return lastTex; } + + @Override + public TextureCoords getTextureCoords() { + return lastTex.getTexture().getImageTexCoords(); + } + protected void attributesUpdated() { int event_mask = 0; @@ -222,7 +230,7 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl { native void _play(long moviePtr); native void _pause(long moviePtr); native void _stop(long moviePtr); - native int _getNextTextureID(long moviePtr); + native int _getNextTextureID(long moviePtr, boolean blocking); native long _getCurrentPosition(long moviePtr); } diff --git a/src/jogl/native/openmax/jogamp_opengl_omx_OMXGLMediaPlayer.c b/src/jogl/native/openmax/jogamp_opengl_omx_OMXGLMediaPlayer.c index 86307ae59..73687f305 100644 --- a/src/jogl/native/openmax/jogamp_opengl_omx_OMXGLMediaPlayer.c +++ b/src/jogl/native/openmax/jogamp_opengl_omx_OMXGLMediaPlayer.c @@ -222,12 +222,12 @@ JNIEXPORT jlong JNICALL Java_jogamp_opengl_omx_OMXGLMediaPlayer__1seek } JNIEXPORT jint JNICALL Java_jogamp_opengl_omx_OMXGLMediaPlayer__1getNextTextureID - (JNIEnv *env, jobject instance, jlong ptr) + (JNIEnv *env, jobject instance, jlong ptr, jboolean blocking) { jint textureID = 0xffffffff; OMXToolBasicAV_t *pOMXAV = (OMXToolBasicAV_t *)((void *)((intptr_t)ptr)); if (pOMXAV != NULL) { - textureID = OMXToolBasicAV_GetNextTextureID(pOMXAV); + textureID = OMXToolBasicAV_GetNextTextureID(pOMXAV, blocking ? 1 : 0); } return textureID; } diff --git a/src/jogl/native/openmax/omx_tool.c b/src/jogl/native/openmax/omx_tool.c index 784d6facf..5e168ad02 100644 --- a/src/jogl/native/openmax/omx_tool.c +++ b/src/jogl/native/openmax/omx_tool.c @@ -1411,9 +1411,9 @@ void OMXToolBasicAV_PlaySeek(OMXToolBasicAV_t * pOMXAV, KDint64 time) kdThreadMutexUnlock(pOMXAV->mutex); } -GLuint OMXToolBasicAV_GetNextTextureID(OMXToolBasicAV_t * pOMXAV) { +GLuint OMXToolBasicAV_GetNextTextureID(OMXToolBasicAV_t * pOMXAV, int blocking) { GLuint texID = 0; - int ret = pOMXAV->glPos; + int idx = pOMXAV->glPos; kdThreadMutexLock(pOMXAV->mutex); if(pOMXAV->status==OMXAV_PLAYING) { @@ -1438,9 +1438,10 @@ GLuint OMXToolBasicAV_GetNextTextureID(OMXToolBasicAV_t * pOMXAV) { pOMXAV->omxPos = next; next = (pOMXAV->omxPos + 1) % pOMXAV->vBufferNum; pOMXAV->filled++; - } - else - { + if(!blocking) { + break; + } + } else { DBG_PRINT2( "GetNextTexture p2.3\n"); break; } @@ -1462,11 +1463,11 @@ GLuint OMXToolBasicAV_GetNextTextureID(OMXToolBasicAV_t * pOMXAV) { pOMXAV->available--; pOMXAV->filled--; pOMXAV->glPos = (pOMXAV->glPos + 1) % pOMXAV->vBufferNum; - ret = pOMXAV->glPos; + idx = pOMXAV->glPos; } } - texID = pOMXAV->available ? pOMXAV->buffers[ret].tex : 0; + texID = pOMXAV->available ? pOMXAV->buffers[idx].tex : 0; DBG_PRINT2( "GetNextTexture B avail %d, filled %d, pos o:%d g:%d t:%d\n", pOMXAV->available, pOMXAV->filled, pOMXAV->omxPos, pOMXAV->glPos, texID); diff --git a/src/jogl/native/openmax/omx_tool.h b/src/jogl/native/openmax/omx_tool.h index be5b8f175..1ade60e4f 100644 --- a/src/jogl/native/openmax/omx_tool.h +++ b/src/jogl/native/openmax/omx_tool.h @@ -139,7 +139,7 @@ void OMXToolBasicAV_PlayStart(OMXToolBasicAV_t * pOMXAV); // #5 void OMXToolBasicAV_PlayPause(OMXToolBasicAV_t * pOMXAV); void OMXToolBasicAV_PlayStop(OMXToolBasicAV_t * pOMXAV); void OMXToolBasicAV_PlaySeek(OMXToolBasicAV_t * pOMXAV, KDint64 time); -GLuint OMXToolBasicAV_GetNextTextureID(OMXToolBasicAV_t * pOMXAV); +GLuint OMXToolBasicAV_GetNextTextureID(OMXToolBasicAV_t * pOMXAV, int blocking); KDint64 OMXToolBasicAV_GetCurrentPosition(OMXToolBasicAV_t * pOMXAV); diff --git a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity.java b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity.java index 43bfd5f61..86b3ffb48 100644 --- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity.java +++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity.java @@ -33,7 +33,6 @@ import java.util.Arrays; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLContext; import javax.media.opengl.GLProfile; import javax.media.opengl.GLRunnable; @@ -47,12 +46,12 @@ import com.jogamp.newt.event.MouseEvent; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.av.GLMediaPlayer; -import com.jogamp.opengl.av.GLMediaPlayerFactory; import com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple; import com.jogamp.opengl.util.Animator; import android.os.Bundle; import android.util.Log; +import android.view.Gravity; public class MovieSimpleActivity extends NewtBaseActivity { static String TAG = "NEWTGearsES2Activity"; @@ -70,10 +69,10 @@ public class MovieSimpleActivity extends NewtBaseActivity { super.onCreate(savedInstanceState); final boolean mPlayerLocal = Boolean.valueOf(System.getProperty("jnlp.mplayer.local")); - final boolean mPlayerNormal = Boolean.valueOf(System.getProperty("jnlp.mplayer.normal")); final boolean mPlayerNoZoom = Boolean.valueOf(System.getProperty("jnlp.mplayer.nozoom")); - final boolean mPlayerShared = !mPlayerNormal && Boolean.valueOf(System.getProperty("jnlp.mplayer.shared")); - Log.d(TAG, "onCreate - 0 - mPlayerLocal "+mPlayerLocal+", mPlayerNormal "+mPlayerNormal+", mPlayerNoScale "+mPlayerNoZoom+", mPlayerShared "+mPlayerShared); + final boolean mPlayerHUD = Boolean.valueOf(System.getProperty("jnlp.mplayer.hud")); + final boolean mPlayerSharedHUD = mPlayerHUD && Boolean.valueOf(System.getProperty("jnlp.mplayer.hud.shared")); + Log.d(TAG, "onCreate - 0 - mPlayerLocal "+mPlayerLocal+", mPlayerNoScale "+mPlayerNoZoom+", mPlayerHUD "+mPlayerHUD+", mPlayerSharedHUD "+mPlayerSharedHUD); String[] urls0 = new String[] { System.getProperty("jnlp.media0_url2"), @@ -85,7 +84,7 @@ public class MovieSimpleActivity extends NewtBaseActivity { final URLConnection urlConnection1; { URLConnection _urlConnection1 = null; - if(!mPlayerShared && !mPlayerNormal) { + if(mPlayerHUD && !mPlayerSharedHUD) { String[] urls1 = new String[] { System.getProperty("jnlp.media1_url0") }; _urlConnection1 = getResource(urls1, 0); } @@ -101,8 +100,7 @@ public class MovieSimpleActivity extends NewtBaseActivity { // also initializes JOGL final GLCapabilities capsMain = new GLCapabilities(GLProfile.getGL2ES2()); - capsMain.setBackgroundOpaque(false); - final GLCapabilities capsHUD = new GLCapabilities(GLProfile.getGL2ES2()); + capsMain.setBackgroundOpaque(!mPlayerHUD); // screen for layout params .. final com.jogamp.newt.Display dpy = NewtFactory.createDisplay(null); @@ -110,82 +108,79 @@ public class MovieSimpleActivity extends NewtBaseActivity { scrn.addReference(); try { - final GLMediaPlayer mPlayerMain = GLMediaPlayerFactory.create(); - mPlayerMain.initStream(urlConnection0); - - final GLMediaPlayer mPlayerHUD; - if(!mPlayerNormal) { - if(mPlayerShared) { - mPlayerHUD = mPlayerMain; - } else { - mPlayerHUD = GLMediaPlayerFactory.create(); - mPlayerHUD.initStream(urlConnection1); - } - } else { - mPlayerHUD = null; - } - final Animator animator = new Animator(); setAnimator(animator); // Main - final MovieSimple demoMain = new MovieSimple(mPlayerMain, false); - if(!mPlayerNormal) { + final MovieSimple demoMain = new MovieSimple(urlConnection0); + if(mPlayerHUD) { demoMain.setEffects(MovieSimple.EFFECT_GRADIENT_BOTTOM2TOP); demoMain.setTransparency(0.9f); } demoMain.setScaleOrig(mPlayerNoZoom); final GLWindow glWindowMain = GLWindow.create(scrn, capsMain); - glWindowMain.setFullscreen(true); - // setContentView(getWindow(), glWindowMain); - viewGroup.addView(((AndroidWindow)glWindowMain.getDelegatedWindow()).getAndroidView()); - registerNEWTWindow(glWindowMain); + { + final int padding = mPlayerHUD ? 32 : 0; + final android.view.View androidView = ((AndroidWindow)glWindowMain.getDelegatedWindow()).getAndroidView(); + glWindowMain.setSize(scrn.getWidth()-padding, scrn.getHeight()-padding); + glWindowMain.setUndecorated(true); + // setContentView(getWindow(), glWindowMain); + viewGroup.addView(androidView, new android.widget.FrameLayout.LayoutParams(glWindowMain.getWidth(), glWindowMain.getHeight(), Gravity.BOTTOM|Gravity.RIGHT)); + registerNEWTWindow(glWindowMain); + } + glWindowMain.addGLEventListener(demoMain); animator.add(glWindowMain); glWindowMain.setVisible(true); - if(null != mPlayerHUD) { - final MovieSimple demoHUD = new MovieSimple(mPlayerHUD, mPlayerShared); - final GLWindow glWindowHUD = GLWindow.create(scrn, capsHUD); - glWindowHUD.addMouseListener(toFrontMouseListener); - { - int x2 = scrn.getX(); - int y2 = scrn.getY(); - int w2 = scrn.getWidth()/2; - int h2 = scrn.getHeight()/2; - if(0 < mPlayerHUD.getWidth() && mPlayerHUD.getWidth()<w2) { - w2 = mPlayerHUD.getWidth(); - } - if(0 < mPlayerHUD.getHeight() && mPlayerHUD.getHeight()<h2) { - h2 = mPlayerHUD.getHeight(); - } - glWindowHUD.setPosition(x2, y2); - glWindowHUD.setSize(w2, h2); - System.err.println("HUD: "+mPlayerHUD); - System.err.println("HUD: "+w2+"x"+h2); - } - // addContentView(getWindow(), glWindowHUD, new android.view.ViewGroup.LayoutParams(glWindowHUD.getWidth(), glWindowHUD.getHeight())); - viewGroup.addView(((AndroidWindow)glWindowHUD.getDelegatedWindow()).getAndroidView(), new android.view.ViewGroup.LayoutParams(glWindowHUD.getWidth(), glWindowHUD.getHeight())); - registerNEWTWindow(glWindowHUD); - glWindowHUD.addGLEventListener(demoHUD); - // Hand over shared ctx must happen while the shared GLWindow is - // guaranteed to be initialized. - glWindowMain.invoke(false, new GLRunnable() { + if(mPlayerHUD) { + final GLMediaPlayer sharedPlayer = mPlayerSharedHUD ? demoMain.getGLMediaPlayer() : null; + final GLCapabilities capsHUD = new GLCapabilities(GLProfile.getGL2ES2()); + capsHUD.setBackgroundOpaque(false); + final GLWindow glWindowHUD = GLWindow.create(scrn, capsHUD); + glWindowMain.invoke(false, new GLRunnable() { @Override public boolean run(GLAutoDrawable drawable) { - if(mPlayerShared) { - GLContext sharedCtx = glWindowMain.getContext(); - System.err.println("Shared: "+sharedCtx); - glWindowHUD.setSharedContext(sharedCtx); - } - animator.add(glWindowHUD); - glWindowHUD.setVisible(true); - glWindowHUD.requestFocus(false); - return true; + int x2 = scrn.getX(); + int y2 = scrn.getY(); + int w2 = scrn.getWidth()/3; + int h2 = scrn.getHeight()/3; + if(null != sharedPlayer) { + if(0 < sharedPlayer.getWidth() && sharedPlayer.getWidth()<scrn.getWidth()/2 && + 0 < sharedPlayer.getHeight() && sharedPlayer.getHeight()<scrn.getHeight()/2) { + w2 = sharedPlayer.getWidth(); + h2 = sharedPlayer.getHeight(); + } + glWindowHUD.setSharedContext(glWindowMain.getContext()); + glWindowHUD.addGLEventListener(new MovieSimple(sharedPlayer)); + } else { + try { + glWindowHUD.addGLEventListener(new MovieSimple(urlConnection1)); + } catch (IOException e) { + e.printStackTrace(); + } + } + glWindowHUD.setPosition(x2, y2); + glWindowHUD.setSize(w2, h2); + System.err.println("HUD: "+mPlayerHUD); + System.err.println("HUD: "+w2+"x"+h2); + glWindowHUD.addMouseListener(toFrontMouseListener); + + viewGroup.post(new Runnable() { + public void run() { + final android.view.View androidView = ((AndroidWindow)glWindowHUD.getDelegatedWindow()).getAndroidView(); + // addContentView(getWindow(), glWindowHUD, new android.view.ViewGroup.LayoutParams(glWindowHUD.getWidth(), glWindowHUD.getHeight())); + viewGroup.addView(androidView, new android.widget.FrameLayout.LayoutParams(glWindowHUD.getWidth(), glWindowHUD.getHeight(), Gravity.TOP|Gravity.LEFT)); + registerNEWTWindow(glWindowHUD); + animator.add(glWindowHUD); + glWindowHUD.setVisible(true); + } } ); + return true; } } ); } animator.setUpdateFPSFrames(60, System.err); + // animator.setUpdateFPSFrames(-1, null); animator.resetFPSCounter(); } catch (IOException e) { e.printStackTrace(); @@ -199,7 +194,7 @@ public class MovieSimpleActivity extends NewtBaseActivity { static URLConnection getResource(String path[], int off) { URLConnection uc = null; for(int i=off; null==uc && i<path.length; i++) { - if(null != path[i]) { + if(null != path[i] && path[i].length()>0) { uc = IOUtil.getResource(path[i], null); Log.d(TAG, "Stream: <"+path[i]+">: "+(null!=uc)); } diff --git a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00a.java b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00a.java index 0fdd2297e..3ad462691 100644 --- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00a.java +++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00a.java @@ -34,17 +34,18 @@ import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties; public class MovieSimpleActivityLauncher00a extends LauncherUtil.BaseActivityLauncher { - static String demo = "com.jogamp.opengl.test.android.MovieSimpleActivity"; + static String demo = "com.jogamp.opengl.test.android.MovieSimpleActivity0"; // static String[] pkgs = new String[] { "com.jogamp.common", "javax.media.opengl", "com.jogamp.opengl.test" }; static String[] pkgs = new String[] { "com.jogamp.opengl.test" }; @Override public void init() { final OrderedProperties props = getProperties(); - props.setProperty("jnlp.mplayer.normal", "true"); - props.setProperty("jnlp.mplayer.nozoom", "true"); - props.setProperty("jnlp.mplayer.shared", "false"); - props.setProperty("jnlp.media0_url2", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_640x360.m4v"); + props.setProperty("jnlp.mplayer.nozoom", "true"); + props.setProperty("jnlp.mplayer.hud", "false"); + props.setProperty("jnlp.mplayer.hud.shared", "false"); + // props.setProperty("jnlp.media0_url2", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_640x360.m4v"); + props.setProperty("jnlp.media0_url2", ""); props.setProperty("jnlp.media0_url1", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4"); props.setProperty("jnlp.media0_url0", "file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4"); props.setProperty("jnlp.media1_url0", "http://archive.org/download/ElephantsDream/ed_1024_512kb.mp4"); diff --git a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00b.java b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00b.java index e52e065c7..a5370e90b 100644 --- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00b.java +++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00b.java @@ -41,10 +41,11 @@ public class MovieSimpleActivityLauncher00b extends LauncherUtil.BaseActivityLau @Override public void init() { final OrderedProperties props = getProperties(); - props.setProperty("jnlp.mplayer.normal", "true"); - props.setProperty("jnlp.mplayer.nozoom", "false"); - props.setProperty("jnlp.mplayer.shared", "false"); - props.setProperty("jnlp.media0_url2", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_640x360.m4v"); + props.setProperty("jnlp.mplayer.nozoom", "false"); + props.setProperty("jnlp.mplayer.hud", "false"); + props.setProperty("jnlp.mplayer.hud.shared", "false"); + // props.setProperty("jnlp.media0_url2", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_640x360.m4v"); + props.setProperty("jnlp.media0_url2", ""); props.setProperty("jnlp.media0_url1", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4"); props.setProperty("jnlp.media0_url0", "file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4"); props.setProperty("jnlp.media1_url0", "http://archive.org/download/ElephantsDream/ed_1024_512kb.mp4"); diff --git a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01a.java b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01a.java index 9e4823a04..ff3fadadf 100644 --- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01a.java +++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01a.java @@ -41,10 +41,11 @@ public class MovieSimpleActivityLauncher01a extends LauncherUtil.BaseActivityLau @Override public void init() { final OrderedProperties props = getProperties(); - props.setProperty("jnlp.mplayer.normal", "false"); - props.setProperty("jnlp.mplayer.nozoom", "true"); - props.setProperty("jnlp.mplayer.shared", "true"); - props.setProperty("jnlp.media0_url2", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_640x360.m4v"); + props.setProperty("jnlp.mplayer.nozoom", "true"); + props.setProperty("jnlp.mplayer.hud", "true"); + props.setProperty("jnlp.mplayer.hud.shared", "true"); + // props.setProperty("jnlp.media0_url2", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_640x360.m4v"); + props.setProperty("jnlp.media0_url2", ""); props.setProperty("jnlp.media0_url1", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4"); props.setProperty("jnlp.media0_url0", "file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4"); props.setProperty("jnlp.media1_url0", "http://archive.org/download/ElephantsDream/ed_1024_512kb.mp4"); diff --git a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01b.java b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01b.java index 81d121b0e..9992ac65a 100644 --- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01b.java +++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01b.java @@ -41,10 +41,11 @@ public class MovieSimpleActivityLauncher01b extends LauncherUtil.BaseActivityLau @Override public void init() { final OrderedProperties props = getProperties(); - props.setProperty("jnlp.mplayer.normal", "false"); - props.setProperty("jnlp.mplayer.nozoom", "false"); - props.setProperty("jnlp.mplayer.shared", "true"); - props.setProperty("jnlp.media0_url2", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_640x360.m4v"); + props.setProperty("jnlp.mplayer.nozoom", "false"); + props.setProperty("jnlp.mplayer.hud", "true"); + props.setProperty("jnlp.mplayer.hud.shared", "true"); + // props.setProperty("jnlp.media0_url2", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_640x360.m4v"); + props.setProperty("jnlp.media0_url2", ""); props.setProperty("jnlp.media0_url1", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4"); props.setProperty("jnlp.media0_url0", "file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4"); props.setProperty("jnlp.media1_url0", "http://archive.org/download/ElephantsDream/ed_1024_512kb.mp4"); diff --git a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher02.java b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher02.java index a907f063a..082cc6335 100644 --- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher02.java +++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher02.java @@ -41,10 +41,11 @@ public class MovieSimpleActivityLauncher02 extends LauncherUtil.BaseActivityLaun @Override public void init() { final OrderedProperties props = getProperties(); - props.setProperty("jnlp.mplayer.normal", "false"); - props.setProperty("jnlp.mplayer.nozoom", "false"); - props.setProperty("jnlp.mplayer.shared", "false"); - props.setProperty("jnlp.media0_url2", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_640x360.m4v"); + props.setProperty("jnlp.mplayer.nozoom", "false"); + props.setProperty("jnlp.mplayer.hud", "true"); + props.setProperty("jnlp.mplayer.hud.shared", "false"); + // props.setProperty("jnlp.media0_url2", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_640x360.m4v"); + props.setProperty("jnlp.media0_url2", ""); props.setProperty("jnlp.media0_url1", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4"); props.setProperty("jnlp.media0_url0", "file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4"); props.setProperty("jnlp.media1_url0", "http://archive.org/download/ElephantsDream/ed_1024_512kb.mp4"); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java index dc1d97396..d32283473 100755 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java @@ -56,7 +56,6 @@ import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.JoglVersion; import com.jogamp.opengl.av.GLMediaPlayer; import com.jogamp.opengl.av.GLMediaEventListener; -import com.jogamp.opengl.av.GLMediaPlayer.TextureFrame; import com.jogamp.opengl.av.GLMediaPlayerFactory; import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.util.Animator; @@ -80,7 +79,6 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener { private long startTime; private int effects = EFFECT_NORMAL; private float alpha = 1.0f; - private int texUnit = 0; public static final int EFFECT_NORMAL = 0; public static final int EFFECT_GRADIENT_BOTTOM2TOP = 1<<1; @@ -90,9 +88,6 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener { public void setOrthoProjection(boolean v) { orthoProjection=v; } public boolean getOrthoProjection() { return orthoProjection; } - public void setTextureUnit(int u) { texUnit = u; } - public int getTextureUnit() { return texUnit; } - public boolean hasEffect(int e) { return 0 != ( effects & e ) ; } public void setEffects(int e) { effects = e; }; public void setTransparency(float alpha) { @@ -149,29 +144,29 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener { }; GLMediaPlayer mPlayer; + URLConnection stream = null; boolean mPlayerExternal; boolean mPlayerShared; boolean mPlayerScaleOrig; public MovieSimple(URLConnection stream) throws IOException { mPlayerScaleOrig = false; + mPlayerShared = false; mPlayerExternal = false; mPlayer = GLMediaPlayerFactory.create(); mPlayer.addEventListener(this); - mPlayer.initStream(stream); - System.out.println("p0.1 "+mPlayer); + this.stream = stream; + System.out.println("pC.1 "+mPlayer); } - public MovieSimple(GLMediaPlayer mediaPlayer, boolean shared) throws IllegalStateException { - if(!shared && GLMediaPlayer.State.UninitializedGL != mediaPlayer.getState()) { - throw new IllegalStateException("Given GLMediaPlayer not in state "+GLMediaPlayer.State.UninitializedGL+": "+mediaPlayer); - } + public MovieSimple(GLMediaPlayer sharedMediaPlayer) throws IllegalStateException { mPlayerScaleOrig = false; - mPlayerShared = shared; + mPlayerShared = true; mPlayerExternal = true; - mPlayer = mediaPlayer; + mPlayer = sharedMediaPlayer; mPlayer.addEventListener(this); - System.out.println("p0.2 shared "+mPlayerShared+", "+mPlayer); + this.stream = null; + System.out.println("pC.2 shared "+mPlayerShared+", "+mPlayer); } public GLMediaPlayer getGLMediaPlayer() { return mPlayer; } @@ -181,13 +176,13 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener { } @Override - public void attributesChanges(GLMediaPlayer mp, int event_mask) { - System.out.println("attributesChanges: "+mp+", 0x"+Integer.toHexString(event_mask)); + public void attributesChanges(GLMediaPlayer mp, int event_mask, long when) { + System.out.println("attributesChanges: "+mp+", 0x"+Integer.toHexString(event_mask)+", when "+when); } @Override - public void newFrameAvailable(GLMediaPlayer mp, TextureFrame frame) { - // System.out.println("newFrameAvailable: "+mp+", "+frame); + public void newFrameAvailable(GLMediaPlayer mp, long when) { + // System.out.println("newFrameAvailable: "+mp+", when "+when); } public void start() { @@ -240,13 +235,16 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener { System.err.println(JoglVersion.getGLInfo(gl, null)); System.err.println("Alpha: "+alpha+", opaque "+drawable.getChosenGLCapabilities().isBackgroundOpaque()+ ", "+drawable.getClass().getName()+", "+drawable); + + gl.glFinish(); boolean useExternalTexture = false; try { + System.out.println("p0 "+mPlayer+", shared "+mPlayerShared); if(!mPlayerShared) { - mPlayer.initGL(gl); + mPlayer.initGLStream(gl, stream); } - System.out.println("p1 "+mPlayer); + System.out.println("p1 "+mPlayer+", shared "+mPlayerShared); useExternalTexture = GLES2.GL_TEXTURE_EXTERNAL_OES == mPlayer.getTextureTarget(); if(useExternalTexture && !gl.isExtensionAvailable("GL_OES_EGL_image_external")) { throw new GLException("GL_OES_EGL_image_external requested but not available"); @@ -274,8 +272,7 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener { if(!st.uniform(gl, pmvMatrixUniform)) { throw new GLException("Error setting PMVMatrix in shader: "+st); } - final GLMediaPlayer.TextureFrame texFrame = mPlayer.getLastTexture(); - if(!st.uniform(gl, new GLUniformData("mgl_ActiveTexture", texUnit))) { + if(!st.uniform(gl, new GLUniformData("mgl_ActiveTexture", mPlayer.getTextureUnit()))) { throw new GLException("Error setting mgl_ActiveTexture in shader: "+st); } @@ -320,7 +317,7 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener { FloatBuffer verticeb = (FloatBuffer)vertices.getBuffer(); GLArrayData texcoord = interleaved.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER); - TextureCoords tc = texFrame.getTexture().getImageTexCoords(); + TextureCoords tc = mPlayer.getTextureCoords(); FloatBuffer texcoordb = (FloatBuffer)texcoord.getBuffer(); GLArrayData colors = interleaved.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER); @@ -364,10 +361,7 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener { } interleaved.seal(gl, true); - // OpenGL Render Settings - // gl.glClearColor(0f, 0f, 0f, 0f); - // gl.glClearColor(0.9f, 0.9f, 0.9f, 0.3f); - gl.glClearColor(0.1f, 0.1f, 0.1f, 0.4f); + gl.glClearColor(0.3f, 0.3f, 0.3f, 0.3f); gl.glEnable(GL2ES2.GL_DEPTH_TEST); @@ -378,7 +372,7 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener { if(null!=mPlayer) { start(); - System.out.println("p1 "+mPlayer); + System.out.println("p2 "+mPlayer); } startTime = System.currentTimeMillis(); @@ -395,25 +389,25 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener { if(null == mPlayer) { return; } winWidth = width; winHeight = height; + + if(null != st) { + reshapePMV(width, height); + GL2ES2 gl = drawable.getGL().getGL2ES2(); + st.useProgram(gl, true); + st.uniform(gl, pmvMatrixUniform); + st.useProgram(gl, false); + } - reshapePMV(width, height); - - GL2ES2 gl = drawable.getGL().getGL2ES2(); - - st.useProgram(gl, true); - st.uniform(gl, pmvMatrixUniform); - st.useProgram(gl, false); - - System.out.println("p2 "+mPlayer); + System.out.println("pR "+mPlayer); } private void reshapePMV(int width, int height) { pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); pmvMatrix.glLoadIdentity(); if(orthoProjection) { - float fw = (float) width; - float fh = (float) height; - pmvMatrix.glOrthof(-fw/2f, fw/2f, -fh/2f, fh/2f, -1.0f, 1.0f); + final float fw = (float) width / 2f; + final float fh = (float) height/ 2f; + pmvMatrix.glOrthof(-fw, fw, -fh, fh, -1.0f, 1.0f); nearPlaneNormalized = 0f; } else { pmvMatrix.gluPerspective(45.0f, (float)width / (float)height, 1f, 10.0f); @@ -430,6 +424,7 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener { if(null == mPlayer) { return; } stop(); + System.out.println("pD.1 "+mPlayer); GL2ES2 gl = drawable.getGL().getGL2ES2(); @@ -437,6 +432,7 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener { if(!mPlayerExternal) { mPlayer.destroy(gl); } + System.out.println("pD.X "+mPlayer); mPlayer=null; pmvMatrixUniform = null; pmvMatrix.destroy(); @@ -448,12 +444,12 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener { public void display(GLAutoDrawable drawable) { if(null == mPlayer) { return; } - GL2ES2 gl = drawable.getGL().getGL2ES2(); - - st.useProgram(gl, true); + GL2ES2 gl = drawable.getGL().getGL2ES2(); gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + st.useProgram(gl, true); + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); pmvMatrix.glLoadIdentity(); pmvMatrix.glTranslatef(0, 0, zoom); @@ -465,27 +461,21 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener { } st.uniform(gl, pmvMatrixUniform); - final Texture tex; if(null!=mPlayer) { final GLMediaPlayer.TextureFrame texFrame; if(mPlayerShared) { texFrame=mPlayer.getLastTexture(); } else { - texFrame=mPlayer.getNextTexture(); + texFrame=mPlayer.getNextTexture(gl, true); + } + if(null != texFrame) { + final Texture tex = texFrame.getTexture(); + gl.glActiveTexture(GL.GL_TEXTURE0+mPlayer.getTextureUnit()); + tex.enable(gl); + tex.bind(gl); + gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); + tex.disable(gl); } - tex = texFrame.getTexture(); - gl.glActiveTexture(GL.GL_TEXTURE0+texUnit); - tex.enable(gl); - tex.bind(gl); - } else { - tex = null; - } - - // Draw a square - gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); - - if(null!=tex) { - tex.disable(gl); } st.useProgram(gl, false); |