From 9e680fe86cd5b64aa758ce32666a6efa19118d3d Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Tue, 3 Apr 2012 22:39:27 +0200 Subject: GLMediaPlayer/MovieSimple: Refine API (split setStream(GL, URL) -> initStream(URL) + initGL(GL)) .. IllegalStateException if wrong. Using internet streams of BigBuckBunny, if avail. - Splitting the initialization in stream and GL allows using the stream information (eg: size, ..) for setting the GLDrawable properties .. - Make the impl. more bullet proof .. --- .../com/jogamp/opengl/av/GLMediaPlayer.java | 42 ++++--- .../android/av/AndroidGLMediaPlayerAPI14.java | 83 ++++++------ .../jogamp/opengl/av/GLMediaPlayerImpl.java | 139 +++++++++++---------- .../jogamp/opengl/omx/OMXGLMediaPlayer.java | 14 +-- .../opengl/test/android/MovieSimpleActivity.java | 98 ++++++++++----- .../test/android/MovieSimpleActivityLauncher.java | 5 +- .../test/junit/jogl/demos/es2/av/MovieSimple.java | 46 +++++-- 7 files changed, 249 insertions(+), 178 deletions(-) diff --git a/src/jogl/classes/com/jogamp/opengl/av/GLMediaPlayer.java b/src/jogl/classes/com/jogamp/opengl/av/GLMediaPlayer.java index 0d07f69ac..95f7cc8b4 100644 --- a/src/jogl/classes/com/jogamp/opengl/av/GLMediaPlayer.java +++ b/src/jogl/classes/com/jogamp/opengl/av/GLMediaPlayer.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.net.URL; import javax.media.opengl.GL; +import javax.media.opengl.GLException; import jogamp.opengl.Debug; @@ -12,17 +13,19 @@ import com.jogamp.opengl.util.texture.Texture; /** * Lifecycle of an GLMediaPlayer: * */ public interface GLMediaPlayer { public static final boolean DEBUG = Debug.debug("GLMediaPlayer"); public enum State { - Uninitialized(0), Stopped(1), Playing(2), Paused(3); + UninitializedStream(0), UninitializedGL(1), Stopped(2), Playing(3), Paused(4); public final int id; @@ -61,21 +64,32 @@ public interface GLMediaPlayer { public int[] getTextureWrapST(); /** - * Sets the stream to be used. Initializes all stream related states and GL resources. - * + * Sets the stream to be used. Initializes all stream related states. + *

+ * UninitializedStream -> UninitializedGL + *

+ * @throws IOException in case of difficulties to open or process the stream + * @throws IllegalStateException if not invoked in state UninitializedStream */ - public void setStream(GL gl, URL url) throws IOException; + public State initStream(URL url) throws IllegalStateException, IOException; + /** + * Initializes all GL related resources. + *

+ * UninitializedGL -> Stopped + *

+ * @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; + /** * Releases the GL and stream resources. *

* ANY -> Uninitialized *

*/ - public void destroy(GL gl); + public State destroy(GL gl); public void setPlaySpeed(float rate); @@ -107,6 +121,8 @@ public interface GLMediaPlayer { public long getCurrentPosition(); /** + * Allowed in state Stopped, Playing and Paused, otherwise ignored. + * * @param msec absolute desired time position in milliseconds * @return time current position in milliseconds, after seeking to the desired position **/ @@ -125,8 +141,6 @@ public interface GLMediaPlayer { */ public TextureFrame getNextTexture(); - public boolean isValid(); - public URL getURL(); /** diff --git a/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java b/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java index a2d9b9bf3..037ab779c 100644 --- a/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java +++ b/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java @@ -53,14 +53,21 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl { // n/a } + @Override + public float getPlaySpeed() { + return 0; + } + @Override protected boolean startImpl() { - try { - mp.start(); - return true; - } catch (IllegalStateException ise) { - if(DEBUG) { - ise.printStackTrace(); + if(null != mp) { + try { + mp.start(); + return true; + } catch (IllegalStateException ise) { + if(DEBUG) { + ise.printStackTrace(); + } } } return false; @@ -68,12 +75,14 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl { @Override protected boolean pauseImpl() { - try { - mp.pause(); - return true; - } catch (IllegalStateException ise) { - if(DEBUG) { - ise.printStackTrace(); + if(null != mp) { + try { + mp.pause(); + return true; + } catch (IllegalStateException ise) { + if(DEBUG) { + ise.printStackTrace(); + } } } return false; @@ -81,21 +90,26 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl { @Override protected boolean stopImpl() { - try { - mp.stop(); - return true; - } catch (IllegalStateException ise) { - if(DEBUG) { - ise.printStackTrace(); + if(null != mp) { + try { + mp.stop(); + return true; + } catch (IllegalStateException ise) { + if(DEBUG) { + ise.printStackTrace(); + } } } return false; } @Override - public long seek(long msec) { - mp.seekTo((int)msec); - return mp.getCurrentPosition(); + protected long seekImpl(long msec) { + if(null != mp) { + mp.seekTo((int)msec); + return mp.getCurrentPosition(); + } + return 0; } @Override @@ -105,7 +119,7 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl { @Override public TextureFrame getNextTexture() { - if(null != atex) { + if(null != atex && null != mp) { final boolean _updateSurface; synchronized(updateSurfaceLock) { _updateSurface = updateSurface; @@ -126,11 +140,6 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl { return null != mp ? mp.getCurrentPosition() : 0; } - @Override - public boolean isValid() { - return null != mp; - } - @Override protected void destroyImpl(GL gl) { if(null != mp) { @@ -140,7 +149,7 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl { } @Override - protected void setStreamImplPreGL() throws IOException { + protected void initStreamImplPreGL() throws IOException { if(null!=mp && null!=url) { try { final Uri uri = Uri.parse(url.toExternalForm()); @@ -152,7 +161,11 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl { } catch (IllegalStateException e) { throw new RuntimeException(e); } - mp.prepare(); + try { + mp.prepare(); + } catch (IOException ioe) { + throw new IOException("MediaPlayer failed to process stream <"+url.toExternalForm()+">: "+ioe.getMessage(), ioe); + } width = mp.getVideoWidth(); height = mp.getVideoHeight(); @@ -165,11 +178,6 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl { } } - @Override - protected void setStreamImplPostGL() throws IOException { - - } - @Override protected void destroyTexImage(GLContext ctx, TextureFrame imgTex) { final AndroidTextureFrame atf = (AndroidTextureFrame) imgTex; @@ -200,10 +208,5 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl { } AndroidGLMediaPlayerAPI14.this.newFrameAvailable(atex); } - }; - - @Override - public float getPlaySpeed() { - return 0; - } + }; } diff --git a/src/jogl/classes/jogamp/opengl/av/GLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/av/GLMediaPlayerImpl.java index 793ee2ea3..5ca402196 100644 --- a/src/jogl/classes/jogamp/opengl/av/GLMediaPlayerImpl.java +++ b/src/jogl/classes/jogamp/opengl/av/GLMediaPlayerImpl.java @@ -8,8 +8,8 @@ import java.util.Iterator; import javax.media.opengl.GL; import javax.media.opengl.GLContext; -import javax.media.opengl.GLDrawable; import javax.media.opengl.GLES2; +import javax.media.opengl.GLException; import com.jogamp.opengl.av.GLMediaPlayer; import com.jogamp.opengl.av.GLMediaEventListener; @@ -36,27 +36,25 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { protected int[] texMinMagFilter = { GL.GL_NEAREST, GL.GL_NEAREST }; protected int[] texWrapST = { GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE }; - private int sWidth = 0; - private int sHeight = 0; protected URL url = null; protected float playSpeed = 1.0f; - /** Shall be set by the {@link #setStreamImplPreGL()} or {@link #setStreamImplPostGL()} method implementation. */ + /** Shall be set by the {@link #initStreamImplPreGL()} method implementation. */ protected int width = 0; - /** Shall be set by the {@link #setStreamImplPreGL()} or {@link #setStreamImplPostGL()}method implementation. */ + /** Shall be set by the {@link #initStreamImplPreGL()} method implementation. */ protected int height = 0; - /** Shall be set by the {@link #setStreamImplPreGL()} or {@link #setStreamImplPostGL()}method implementation. */ + /** Shall be set by the {@link #initStreamImplPreGL()} method implementation. */ protected int fps = 0; - /** Shall be set by the {@link #setStreamImplPreGL()} or {@link #setStreamImplPostGL()}method implementation. */ + /** Shall be set by the {@link #initStreamImplPreGL()} method implementation. */ protected long bps = 0; - /** In frames. Shall be set by the {@link #setStreamImplPreGL()} or {@link #setStreamImplPostGL()}method implementation. */ + /** In frames. Shall be set by the {@link #initStreamImplPreGL()} method implementation. */ protected long totalFrames = 0; - /** In ms. Shall be set by the {@link #setStreamImplPreGL()} or {@link #setStreamImplPostGL()}method implementation. */ + /** In ms. Shall be set by the {@link #initStreamImplPreGL()} method implementation. */ protected long duration = 0; - /** Shall be set by the {@link #setStreamImplPreGL()} or {@link #setStreamImplPostGL()}method implementation. */ + /** Shall be set by the {@link #initStreamImplPreGL()} method implementation. */ protected String acodec = null; - /** Shall be set by the {@link #setStreamImplPreGL()} or {@link #setStreamImplPostGL()}method implementation. */ + /** Shall be set by the {@link #initStreamImplPreGL()} method implementation. */ protected String vcodec = null; protected long frameNumber = 0; @@ -68,7 +66,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { protected GLMediaPlayerImpl() { this.textureCount=3; this.textureTarget=GL.GL_TEXTURE_2D; - this.state = State.Uninitialized; + this.state = State.UninitializedStream; } protected final void setTextureCount(int textureCount) { @@ -119,20 +117,34 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { } protected abstract boolean stopImpl(); + public final long seek(long msec) { + final long cp; + switch(state) { + case Stopped: + case Playing: + case Paused: + cp = seekImpl(msec); + break; + default: + cp = 0; + } + return cp; + } + protected abstract long seekImpl(long msec); + public final State getState() { return state; } @Override - public final void setStream(GL gl, URL url) throws IOException { - if(State.Uninitialized != state) { - destroy(gl); + public final State initStream(URL url) throws IllegalStateException, IOException { + if(State.UninitializedStream != state) { + throw new IllegalStateException("Instance not in state "+State.UninitializedStream+", but "+state); } this.url = url; if (this.url != null) { - setStreamImplPreGL(); - init(gl); - setStreamImplPostGL(); - state = State.Stopped; + initStreamImplPreGL(); + state = State.UninitializedGL; } + return state; } /** @@ -145,52 +157,44 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { * @see #acodec * @see #vcodec */ - protected abstract void setStreamImplPreGL() throws IOException; + protected abstract void initStreamImplPreGL() throws IOException; - /** - * Implementation shall set the following set of data here or at {@link #setStreamImplPreGL()} - * @see #width - * @see #height - * @see #fps - * @see #bps - * @see #totalFrames - * @see #acodec - * @see #vcodec - */ - protected abstract void setStreamImplPostGL() throws IOException; - - protected final void init(GL gl) { + @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); + } final GLContext ctx = gl.getContext(); if(!ctx.isCurrent()) { - throw new RuntimeException("Not current: "+ctx); + throw new GLException("Not current: "+ctx); } + + try { + if(null!=texFrames) { + removeAllImageTextures(ctx); + } else { + texFrames = new TextureFrame[textureCount]; + } - final GLDrawable drawable = ctx.getGLDrawable(); - sWidth = drawable.getWidth(); - sHeight = drawable.getHeight(); - System.out.println("surface size: "+sWidth+"x"+sHeight); - System.out.println("Platform Extensions : "+ctx.getPlatformExtensionsString()); - - 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)); + 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: "+(null!=uc)); + } + } + return uc; + } } diff --git a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher.java index 36bdd2921..474e523e4 100644 --- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher.java +++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher.java @@ -40,7 +40,10 @@ public class MovieSimpleActivityLauncher extends LauncherUtil.BaseActivityLaunch @Override public void init() { - final OrderedProperties props = getProperties(); + final OrderedProperties props = getProperties(); + props.setProperty("jnlp.media0_url2", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_640x360.m4v"); + 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("jogamp.debug.JNILibLoader", "true"); // props.setProperty("jogamp.debug.NativeLibrary", "true"); // props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); 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 9730a16c5..4c156b8f0 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 @@ -76,7 +76,6 @@ public class MovieSimple implements MouseListener, GLEventListener, GLMediaEvent private float ang = 0f; private long startTime; private long curTime; - private URL stream; private int effects = EFFECT_NORMAL; private float alpha = 1.0f; @@ -144,10 +143,27 @@ public class MovieSimple implements MouseListener, GLEventListener, GLMediaEvent public void mouseWheelMoved(MouseEvent e) { } - public MovieSimple(URL stream) { - this.stream = stream ; + GLMediaPlayer mPlayer; + boolean mPlayerExternal; + + public MovieSimple(URL stream) throws IOException { + mPlayerExternal = false; + mPlayer = GLMediaPlayerFactory.create(); + mPlayer.addEventListener(this); + mPlayer.initStream(stream); + System.out.println("p0.1 "+mPlayer); } + public MovieSimple(GLMediaPlayer mediaPlayer) throws IllegalStateException { + if(GLMediaPlayer.State.UninitializedGL != mediaPlayer.getState()) { + throw new IllegalStateException("Given GLMediaPlayer not in state "+GLMediaPlayer.State.UninitializedGL+": "+mediaPlayer); + } + mPlayerExternal = true; + mPlayer = mediaPlayer; + mPlayer.addEventListener(this); + System.out.println("p0.2 "+mPlayer); + } + private void run() { System.err.println("MovieSimple.run()"); try { @@ -203,8 +219,6 @@ public class MovieSimple implements MouseListener, GLEventListener, GLMediaEvent st.attachShaderProgram(gl, sp, false); } - GLMediaPlayer mPlayer=null; - public void init(GLAutoDrawable drawable) { GL2ES2 gl = drawable.getGL().getGL2ES2(); System.err.println("Entering initialization"); @@ -216,14 +230,17 @@ public class MovieSimple implements MouseListener, GLEventListener, GLMediaEvent boolean useExternalTexture = false; try { - mPlayer = GLMediaPlayerFactory.create(); - mPlayer.addEventListener(this); - // movie.setStream(4, new URL(stream)); - mPlayer.setStream(gl, stream); - System.out.println("p0 "+mPlayer); + mPlayer.initGL(gl); + System.out.println("p1 "+mPlayer); useExternalTexture = GLES2.GL_TEXTURE_EXTERNAL_OES == mPlayer.getTextureTarget(); mPlayer.setTextureMinMagFilter( new int[] { GL.GL_NEAREST, GL.GL_LINEAR } ); - } catch (IOException ioe) { ioe.printStackTrace(); } + } catch (GLException glex) { + if(null != mPlayer) { + mPlayer.destroy(gl); + mPlayer = null; + } + throw new GLException(glex); + } pmvMatrix = new PMVMatrix(); @@ -331,6 +348,7 @@ public class MovieSimple implements MouseListener, GLEventListener, GLMediaEvent } public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + if(null == mPlayer) { return; } winWidth = width; winHeight = height; @@ -355,6 +373,8 @@ public class MovieSimple implements MouseListener, GLEventListener, GLMediaEvent } public void dispose(GLAutoDrawable drawable) { + if(null == mPlayer) { return; } + GL2ES2 gl = drawable.getGL().getGL2ES2(); mPlayer.destroy(gl); @@ -368,6 +388,8 @@ public class MovieSimple implements MouseListener, GLEventListener, GLMediaEvent } public void display(GLAutoDrawable drawable) { + if(null == mPlayer) { return; } + GL2ES2 gl = drawable.getGL().getGL2ES2(); st.useProgram(gl, true); @@ -412,7 +434,7 @@ public class MovieSimple implements MouseListener, GLEventListener, GLMediaEvent public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) { } - public static void main(String[] args) throws MalformedURLException { + public static void main(String[] args) throws IOException, MalformedURLException { String fname="file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4"; if(args.length>0) fname=args[0]; new MovieSimple(new URL(fname)).run(); -- cgit v1.2.3