diff options
author | Sven Gothel <[email protected]> | 2012-04-03 18:49:24 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2012-04-03 18:49:24 +0200 |
commit | c594cf1dc9f37dd1a6d861a1aa5426abbd082d60 (patch) | |
tree | f72ea63ca9040b17b6203b63e9c7c3678a1881eb /src/jogl/classes/jogamp | |
parent | 48581e36773e58e20a3e780caf5b1c29b4805285 (diff) |
GLMediaPlayer: API and implementation update. First working version on Android API 14
- Introduce states
- Customize / Access texture target,count,features.
- Expose TextureFrame.
- Use 'long' for all time values in msec.
- Mark information optional in API doc (fps, bps, ..)
Diffstat (limited to 'src/jogl/classes/jogamp')
3 files changed, 242 insertions, 146 deletions
diff --git a/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java b/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java index adfe2a048..a2d9b9bf3 100644 --- a/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java +++ b/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java @@ -1,11 +1,9 @@ package jogamp.opengl.android.av; import java.io.IOException; -import java.net.URL; import javax.media.opengl.GL; import javax.media.opengl.GLContext; -import javax.media.opengl.GLDrawable; import javax.media.opengl.GLES2; import jogamp.common.os.android.StaticContext; @@ -17,12 +15,7 @@ import android.media.MediaPlayer; import android.net.Uri; import android.view.Surface; -import com.jogamp.opengl.av.GLMediaEventListener; -import com.jogamp.opengl.av.GLMediaPlayer; -import com.jogamp.opengl.av.GLMediaPlayer.TextureFrame; -import com.jogamp.opengl.util.PMVMatrix; import com.jogamp.opengl.util.texture.Texture; -import com.jogamp.opengl.util.texture.TextureCoords; /*** * Android API Level 14: {@link MediaPlayer#setSurface(Surface)} @@ -31,6 +24,8 @@ import com.jogamp.opengl.util.texture.TextureCoords; public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl { MediaPlayer mp; boolean updateSurface = false; + Object updateSurfaceLock = new Object(); + AndroidTextureFrame atex = null; public static class AndroidTextureFrame extends TextureFrame { public AndroidTextureFrame(Texture t, SurfaceTexture stex) { @@ -59,137 +54,156 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl { } @Override - public void start() { - mp.start(); + protected boolean startImpl() { + try { + mp.start(); + return true; + } catch (IllegalStateException ise) { + if(DEBUG) { + ise.printStackTrace(); + } + } + return false; } @Override - public void pause() { - mp.pause(); + protected boolean pauseImpl() { + try { + mp.pause(); + return true; + } catch (IllegalStateException ise) { + if(DEBUG) { + ise.printStackTrace(); + } + } + return false; } @Override - public void stop() { - mp.stop(); + protected boolean stopImpl() { + try { + mp.stop(); + return true; + } catch (IllegalStateException ise) { + if(DEBUG) { + ise.printStackTrace(); + } + } + return false; } - + @Override - public int seek(int msec) { - mp.seekTo(msec); + public long seek(long msec) { + mp.seekTo((int)msec); return mp.getCurrentPosition(); } @Override - public Texture getNextTextureID() { - // TODO Auto-generated method stub - return null; + public TextureFrame getLastTexture() { + return atex; } @Override - public int getCurrentPosition() { - return mp.getCurrentPosition(); + public TextureFrame getNextTexture() { + if(null != atex) { + final boolean _updateSurface; + synchronized(updateSurfaceLock) { + _updateSurface = updateSurface; + updateSurface = false; + } + if(_updateSurface) { + atex.getSurfaceTexture().updateTexImage(); + // atex.getSurfaceTexture().getTransformMatrix(atex.getSTMatrix()); + } + return atex; + } else { + return null; + } + } + + @Override + public long getCurrentPosition() { + return null != mp ? mp.getCurrentPosition() : 0; } @Override public boolean isValid() { - return true; + return null != mp; } - AndroidTextureFrame androidTextureFrame = null; - @Override protected void destroyImpl(GL gl) { - mp.release(); - mp = null; + if(null != mp) { + mp.release(); + mp = null; + } } @Override - protected void setStreamImpl() throws IOException { - try { - final Uri uri = Uri.parse(url.toExternalForm()); - mp.setDataSource(StaticContext.getContext(), uri); - } catch (IllegalArgumentException e) { - throw new RuntimeException(e); - } catch (SecurityException e) { - throw new RuntimeException(e); - } catch (IllegalStateException e) { - throw new RuntimeException(e); + protected void setStreamImplPreGL() throws IOException { + if(null!=mp && null!=url) { + try { + final Uri uri = Uri.parse(url.toExternalForm()); + mp.setDataSource(StaticContext.getContext(), uri); + } catch (IllegalArgumentException e) { + throw new RuntimeException(e); + } catch (SecurityException e) { + throw new RuntimeException(e); + } catch (IllegalStateException e) { + throw new RuntimeException(e); + } + mp.prepare(); + + width = mp.getVideoWidth(); + height = mp.getVideoHeight(); + fps = 0; + bps = 0; + totalFrames = 0; + duration = mp.getDuration(); + acodec = "unknown"; + vcodec = "unknown"; } - mp.prepare(); + } + + @Override + protected void setStreamImplPostGL() throws IOException { - width = mp.getVideoWidth(); - height = mp.getVideoHeight(); - fps = 0; - bps = 0; - totalFrames = mp.getDuration(); - acodec = "unknown"; - vcodec = "unknown"; } @Override protected void destroyTexImage(GLContext ctx, TextureFrame imgTex) { final AndroidTextureFrame atf = (AndroidTextureFrame) imgTex; atf.getSurfaceTexture().release(); + atex = null; super.destroyTexImage(ctx, imgTex); } @Override protected AndroidTextureFrame createTexImage(GLContext ctx, int idx, int[] tex) { - final GL gl = ctx.getGL(); - - if( 0 > tex[idx] ) { - throw new RuntimeException("TextureName "+toHexString(tex[idx])+" invalid."); - } - gl.glBindTexture(GLES2.GL_TEXTURE_EXTERNAL_OES, tex[idx]); - { - final int err = gl.glGetError(); - if( GL.GL_NO_ERROR != err ) { - throw new RuntimeException("Couldn't bind textureName "+toHexString(tex[idx])+" to 2D target, err "+toHexString(err)); - } - } - // gl.glTexParameterf(GLES2.GL_TEXTURE_EXTERNAL_OES, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR); - // gl.glTexParameterf(GLES2.GL_TEXTURE_EXTERNAL_OES, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); - gl.glTexParameterf(GLES2.GL_TEXTURE_EXTERNAL_OES, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST); - gl.glTexParameterf(GLES2.GL_TEXTURE_EXTERNAL_OES, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST); - // Clamp to edge is only option. - gl.glTexParameteri(GLES2.GL_TEXTURE_EXTERNAL_OES, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE); - gl.glTexParameteri(GLES2.GL_TEXTURE_EXTERNAL_OES, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE); + final Texture texture = super.createTexImageImpl(ctx, idx, tex, true); - SurfaceTexture stex = new SurfaceTexture(tex[idx]); + final SurfaceTexture stex = new SurfaceTexture(tex[idx]); stex.setOnFrameAvailableListener(onFrameAvailableListener); + final Surface surf = new Surface(stex); + mp.setSurface(surf); + surf.release(); - return new AndroidTextureFrame( com.jogamp.opengl.util.texture.TextureIO.newTexture(tex[idx], - GLES2.GL_TEXTURE_EXTERNAL_OES, - width, height, - width, height, - true), stex); + atex = new AndroidTextureFrame( texture, stex ); + return atex; } protected OnFrameAvailableListener onFrameAvailableListener = new OnFrameAvailableListener() { @Override public void onFrameAvailable(SurfaceTexture surfaceTexture) { - frameNumber++; - updateSurface = true; + synchronized(updateSurfaceLock) { + updateSurface = true; + } + AndroidGLMediaPlayerAPI14.this.newFrameAvailable(atex); } }; @Override public float getPlaySpeed() { - // TODO Auto-generated method stub return 0; } - - private float[] mSTMatrix = new float[16]; - - @Override - public Texture getLastTextureID() { - if(updateSurface) { - androidTextureFrame.getSurfaceTexture().updateTexImage(); - androidTextureFrame.getSurfaceTexture().getTransformMatrix(mSTMatrix); - TextureCoords tc = androidTextureFrame.getTexture().getImageTexCoords(); - PMVMatrix pmv; - } - return androidTextureFrame.getTexture(); - } - } diff --git a/src/jogl/classes/jogamp/opengl/av/GLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/av/GLMediaPlayerImpl.java index 826bb6953..793ee2ea3 100644 --- a/src/jogl/classes/jogamp/opengl/av/GLMediaPlayerImpl.java +++ b/src/jogl/classes/jogamp/opengl/av/GLMediaPlayerImpl.java @@ -29,29 +29,34 @@ import com.jogamp.opengl.util.texture.Texture; */ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { + protected State state; protected int textureCount; protected int textureTarget; + 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 Texture texture = null; protected float playSpeed = 1.0f; - /** Shall be set by the {@link #setStreamImpl()} method implementation. */ + /** Shall be set by the {@link #setStreamImplPreGL()} or {@link #setStreamImplPostGL()} method implementation. */ protected int width = 0; - /** Shall be set by the {@link #setStreamImpl()} method implementation. */ + /** Shall be set by the {@link #setStreamImplPreGL()} or {@link #setStreamImplPostGL()}method implementation. */ protected int height = 0; - /** Shall be set by the {@link #setStreamImpl()} method implementation. */ + /** Shall be set by the {@link #setStreamImplPreGL()} or {@link #setStreamImplPostGL()}method implementation. */ protected int fps = 0; - /** Shall be set by the {@link #setStreamImpl()} method implementation. */ + /** Shall be set by the {@link #setStreamImplPreGL()} or {@link #setStreamImplPostGL()}method implementation. */ protected long bps = 0; - /** Shall be set by the {@link #setStreamImpl()} method implementation. */ + /** In frames. Shall be set by the {@link #setStreamImplPreGL()} or {@link #setStreamImplPostGL()}method implementation. */ protected long totalFrames = 0; - /** Shall be set by the {@link #setStreamImpl()} method implementation. */ + /** In ms. Shall be set by the {@link #setStreamImplPreGL()} or {@link #setStreamImplPostGL()}method implementation. */ + protected long duration = 0; + /** Shall be set by the {@link #setStreamImplPreGL()} or {@link #setStreamImplPostGL()}method implementation. */ protected String acodec = null; - /** Shall be set by the {@link #setStreamImpl()} method implementation. */ + /** Shall be set by the {@link #setStreamImplPreGL()} or {@link #setStreamImplPostGL()}method implementation. */ protected String vcodec = null; protected long frameNumber = 0; @@ -63,29 +68,75 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { protected GLMediaPlayerImpl() { this.textureCount=3; this.textureTarget=GL.GL_TEXTURE_2D; + this.state = State.Uninitialized; } protected final void setTextureCount(int textureCount) { this.textureCount=textureCount; } + public final int getTextureCount() { return textureCount; } + protected final void setTextureTarget(int textureTarget) { this.textureTarget=textureTarget; } + public final int getTextureTarget() { return textureTarget; } + + public final void setTextureMinMagFilter(int[] minMagFilter) { texMinMagFilter[0] = minMagFilter[0]; texMinMagFilter[1] = minMagFilter[1];} + public final int[] getTextureMinMagFilter() { return texMinMagFilter; } + + public final void setTextureWrapST(int[] wrapST) { texWrapST[0] = wrapST[0]; texWrapST[1] = wrapST[1];} + public final int[] getTextureWrapST() { return texWrapST; } + + public final State start() { + switch(state) { + case Stopped: + case Paused: + if(startImpl()) { + state = State.Playing; + } + } + return state; + } + protected abstract boolean startImpl(); + + public final State pause() { + if(State.Playing == state && pauseImpl()) { + state = State.Paused; + } + return state; + } + protected abstract boolean pauseImpl(); + + public final State stop() { + switch(state) { + case Playing: + case Paused: + if(stopImpl()) { + state = State.Stopped; + } + } + return state; + } + protected abstract boolean stopImpl(); + + public final State getState() { return state; } @Override public final void setStream(GL gl, URL url) throws IOException { + if(State.Uninitialized != state) { + destroy(gl); + } this.url = url; - if (this.url == null) { - System.out.println("setURL (null)"); - stop(); - return; + if (this.url != null) { + setStreamImplPreGL(); + init(gl); + setStreamImplPostGL(); + state = State.Stopped; } - setStreamImpl(); - init(gl); } /** - * Implementation shall set the following set of data: + * Implementation shall set the following set of data here or at {@link #setStreamImplPostGL()} * @see #width * @see #height * @see #fps @@ -94,8 +145,20 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { * @see #acodec * @see #vcodec */ - protected abstract void setStreamImpl() throws IOException; + protected abstract void setStreamImplPreGL() 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) { final GLContext ctx = gl.getContext(); if(!ctx.isCurrent()) { @@ -147,28 +210,29 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { } } - // create space for buffer with a texture - gl.glTexImage2D( - textureTarget, // target - 0, // level - GL.GL_RGBA, // internal format - width, // width - height, // height - 0, // border - GL.GL_RGBA, // format - GL.GL_UNSIGNED_BYTE, // type - null); // pixels -- will be provided later - { - final int err = gl.glGetError(); - if( GL.GL_NO_ERROR != err ) { - throw new RuntimeException("Couldn't create TexImage2D RGBA "+width+"x"+height+", err "+toHexString(err)); + if(GLES2.GL_TEXTURE_EXTERNAL_OES != textureTarget) { + // create space for buffer with a texture + gl.glTexImage2D( + textureTarget, // target + 0, // level + GL.GL_RGBA, // internal format + width, // width + height, // height + 0, // border + GL.GL_RGBA, // format + GL.GL_UNSIGNED_BYTE, // type + null); // pixels -- will be provided later + { + final int err = gl.glGetError(); + if( GL.GL_NO_ERROR != err ) { + throw new RuntimeException("Couldn't create TexImage2D RGBA "+width+"x"+height+", err "+toHexString(err)); + } } } - gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST); - gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST); - // Clamp to edge is only option. - gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE); - gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE); + gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MIN_FILTER, texMinMagFilter[0]); + gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MAG_FILTER, texMinMagFilter[0]); + gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_S, texWrapST[0]); + gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_T, texWrapST[1]); return com.jogamp.opengl.util.texture.TextureIO.newTexture(tex[idx], textureTarget, @@ -182,7 +246,6 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { } protected void removeAllImageTextures(GLContext ctx) { - texture = null; for(int i=0; i<textureCount; i++) { final TextureFrame imgTex = texFrames[i]; destroyTexImage(ctx, imgTex); @@ -199,6 +262,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { } } protected void newFrameAvailable(TextureFrame frame) { + frameNumber++; synchronized(eventListenersLock) { for(Iterator<GLMediaEventListener> i = eventListeners.iterator(); i.hasNext(); ) { i.next().newFrameAvailable(this, frame); @@ -212,14 +276,10 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { } @Override - public synchronized Texture getLastTextureID() { - return texture; - } - - @Override public synchronized void destroy(GL gl) { destroyImpl(gl); removeAllImageTextures(gl.getContext()); + state = State.Uninitialized; } protected abstract void destroyImpl(GL gl); @@ -244,6 +304,11 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { } @Override + public synchronized long getDuration() { + return duration; + } + + @Override public synchronized long getBitrate() { return bps; } @@ -265,7 +330,8 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { @Override public synchronized String toString() { - return "GLMediaPlayer [ stream [ video [ "+vcodec+", "+width+"x"+height+", "+fps+"fps, "+bps+"bsp, "+totalFrames+"f ] ] ]"; + 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]]]"; } @Override diff --git a/src/jogl/classes/jogamp/opengl/omx/OMXGLMediaPlayer.java b/src/jogl/classes/jogamp/opengl/omx/OMXGLMediaPlayer.java index 8f5f9c3ab..23eadcd27 100644 --- a/src/jogl/classes/jogamp/opengl/omx/OMXGLMediaPlayer.java +++ b/src/jogl/classes/jogamp/opengl/omx/OMXGLMediaPlayer.java @@ -10,7 +10,7 @@ import javax.media.opengl.GLContext; import javax.media.opengl.GLException; import com.jogamp.opengl.av.GLMediaEventListener; -import com.jogamp.opengl.util.texture.Texture; +import com.jogamp.opengl.av.GLMediaPlayer.TextureFrame; import jogamp.opengl.av.EGLMediaPlayerImpl; import jogamp.opengl.egl.EGL; @@ -26,7 +26,10 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl { protected int o_fps = 0; protected long o_bps = 0; protected long o_totalFrames = 0; + protected long o_duration = 0; + protected TextureFrame lastTex = null; + public OMXGLMediaPlayer() { super(TextureType.KHRImage, true); initOMX(); @@ -43,6 +46,7 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl { protected TextureFrame createTexImage(GLContext ctx, int idx, int[] tex) { final EGLTextureFrame eglTex = (EGLTextureFrame) super.createTexImage(ctx, idx, tex); _setStreamEGLImageTexture2D(moviePtr, idx, tex[idx], eglTex.getImage(), eglTex.getSync()); + lastTex = eglTex; return eglTex; } @@ -61,7 +65,7 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl { } @Override - protected void setStreamImpl() throws IOException { + protected void setStreamImplPreGL() throws IOException { if(0==moviePtr) { throw new GLException("OMX native instance null"); } @@ -91,9 +95,13 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl { System.out.println("setURL: p2 "+this); } + @Override + protected void setStreamImplPostGL() throws IOException { + + } @Override - public synchronized int getCurrentPosition() { + public synchronized long getCurrentPosition() { if(0==moviePtr) { throw new GLException("OMX native instance null"); } @@ -114,36 +122,38 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl { playSpeed = rate; } - /** @return time position after issuing the command */ @Override - public synchronized void start() { + public synchronized boolean startImpl() { if(0==moviePtr) { - throw new GLException("OMX native instance null"); + return false; } _play(moviePtr); + return true; } /** @return time position after issuing the command */ @Override - public synchronized void pause() { + public synchronized boolean pauseImpl() { if(0==moviePtr) { - throw new GLException("OMX native instance null"); + return false; } _pause(moviePtr); + return true; } /** @return time position after issuing the command */ @Override - public synchronized void stop() { + public synchronized boolean stopImpl() { if(0==moviePtr) { - throw new GLException("OMX native instance null"); + return false; } _stop(moviePtr); + return true; } /** @return time position after issuing the command */ @Override - public synchronized int seek(int msec) { + public synchronized long seek(long msec) { if(0==moviePtr) { throw new GLException("OMX native instance null"); } @@ -151,16 +161,21 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl { } @Override - public synchronized Texture getNextTextureID() { + public TextureFrame getLastTexture() { + return lastTex; + } + + @Override + public synchronized TextureFrame getNextTexture() { if(0==moviePtr) { throw new GLException("OMX native instance null"); } - texture=null; + lastTex=null; TextureFrame eglImgTex = texFrameMap.get(new Integer(_getNextTextureID(moviePtr))); if(null!=eglImgTex) { - texture = eglImgTex.getTexture(); + lastTex = eglImgTex; } - return texture; + return lastTex; } protected void attributesUpdated() { @@ -192,6 +207,7 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl { o_fps = fps; o_bps = bps; o_totalFrames = totalFrames; + o_duration = duration; } private String replaceAll(String orig, String search, String repl) { @@ -227,12 +243,12 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl { native void _activateStream(long moviePtr); native void _setStreamEGLImageTexture2D(long moviePtr, int i, int tex, long image, long sync); - native int _seek(long moviePtr, int position); + native long _seek(long moviePtr, long position); native void _setPlaySpeed(long moviePtr, float rate); native void _play(long moviePtr); native void _pause(long moviePtr); native void _stop(long moviePtr); native int _getNextTextureID(long moviePtr); - native int _getCurrentPosition(long moviePtr); + native long _getCurrentPosition(long moviePtr); } |