diff options
author | Sven Gothel <[email protected]> | 2012-04-16 21:18:03 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2012-04-16 21:18:03 +0200 |
commit | 35beeabffed61e1597aaffc0c5926ab5ef86d32e (patch) | |
tree | 6a7e91c07e7d61613b03f35a17486faf01b211fc /src/jogl/classes/jogamp/opengl/util/av | |
parent | 2f0583aad39f93a934629c21beac66a758373249 (diff) |
TextureSequence Shader Support; GLMediaPlayer uses 'int' where possible; General enhancments.
For details about TextureSequence/GLMediaPlayer shader collaboration w/ your own shader source,
see TextureSequence and TexCubeES2 / MovieSimple demo.
TextureSequence allows implementations to provide their own texture lookup function
which may provide color space conversion (YUV) .. or other runtime hw-accel features.
Have a look at the next commit, which provides an Libav/FFMpeg implementation w/ YUV/RGB shader conversion.
MovieCube adds keyboard control (Android: firm touch on display to launch keyboard, don't break it though :)
Diffstat (limited to 'src/jogl/classes/jogamp/opengl/util/av')
4 files changed, 316 insertions, 154 deletions
diff --git a/src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java index 52378d0fd..31f13297b 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java +++ b/src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java @@ -27,6 +27,7 @@ */ package jogamp.opengl.util.av; +import java.nio.Buffer; import java.nio.IntBuffer; import javax.media.opengl.GL; @@ -41,8 +42,8 @@ import jogamp.opengl.egl.EGLDrawable; import jogamp.opengl.egl.EGLExt; public abstract class EGLMediaPlayerImpl extends GLMediaPlayerImpl { - TextureType texType; - boolean useKHRSync; + final protected TextureType texType; + final protected boolean useKHRSync; public enum TextureType { GL(0), KHRImage(1); @@ -56,18 +57,21 @@ public abstract class EGLMediaPlayerImpl extends GLMediaPlayerImpl { public static class EGLTextureFrame extends TextureSequence.TextureFrame { - public EGLTextureFrame(Texture t, long khrImage, long khrSync) { + public EGLTextureFrame(Buffer clientBuffer, Texture t, long khrImage, long khrSync) { super(t); + this.clientBuffer = clientBuffer; this.image = khrImage; this.sync = khrSync; } + public final Buffer getClientBuffer() { return clientBuffer; } public final long getImage() { return image; } public final long getSync() { return sync; } public String toString() { - return "EGLTextureFrame[" + texture + ", img "+ image + ", sync "+ sync+"]"; + return "EGLTextureFrame[" + texture + ", img "+ image + ", sync "+ sync+", clientBuffer "+clientBuffer+"]"; } + protected final Buffer clientBuffer; protected final long image; protected final long sync; } @@ -85,30 +89,43 @@ public abstract class EGLMediaPlayerImpl extends GLMediaPlayerImpl { @Override protected TextureSequence.TextureFrame createTexImage(GL gl, int idx, int[] tex) { - final Texture texture = super.createTexImageImpl(gl, idx, tex, true); + final Texture texture = super.createTexImageImpl(gl, idx, tex, width, height, false); + final Buffer clientBuffer; final long image; final long sync; + final boolean eglUsage = TextureType.KHRImage == texType || useKHRSync ; + final EGLContext eglCtx; + final EGLExt eglExt; + final EGLDrawable eglDrawable; - 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(eglUsage) { + eglCtx = (EGLContext) gl.getContext(); + eglExt = eglCtx.getEGLExt(); + eglDrawable = (EGLDrawable) eglCtx.getGLDrawable(); + } else { + eglCtx = null; + eglExt = null; + eglDrawable = null; + } if(TextureType.KHRImage == texType) { + IntBuffer nioTmp = Buffers.newDirectIntBuffer(1); // create EGLImage from texture + clientBuffer = null; // FIXME nioTmp.put(0, EGL.EGL_NONE); image = eglExt.eglCreateImageKHR( eglDrawable.getDisplay(), eglCtx.getHandle(), EGLExt.EGL_GL_TEXTURE_2D_KHR, - null /* buffer */, nioTmp); + clientBuffer, nioTmp); if (0==image) { throw new RuntimeException("EGLImage creation failed: "+EGL.eglGetError()+", ctx "+eglCtx+", tex "+tex[idx]+", err "+toHexString(EGL.eglGetError())); } } else { + clientBuffer = null; image = 0; } if(useKHRSync) { + int[] tmp = new int[1]; // Create sync object so that we can be sure that gl has finished // rendering the EGLImage texture before we tell OpenMAX to fill // it with a new frame. @@ -120,14 +137,25 @@ public abstract class EGLMediaPlayerImpl extends GLMediaPlayerImpl { } else { sync = 0; } - return new EGLTextureFrame(texture, image, sync); + return new EGLTextureFrame(clientBuffer, texture, image, sync); } @Override protected void destroyTexImage(GL gl, TextureSequence.TextureFrame imgTex) { - final EGLContext eglCtx = (EGLContext) gl.getContext(); - final EGLExt eglExt = eglCtx.getEGLExt(); - final EGLDrawable eglDrawable = (EGLDrawable) eglCtx.getGLDrawable(); + final boolean eglUsage = TextureType.KHRImage == texType || useKHRSync ; + final EGLContext eglCtx; + final EGLExt eglExt; + final EGLDrawable eglDrawable; + + if(eglUsage) { + eglCtx = (EGLContext) gl.getContext(); + eglExt = eglCtx.getEGLExt(); + eglDrawable = (EGLDrawable) eglCtx.getGLDrawable(); + } else { + eglCtx = null; + eglExt = null; + eglDrawable = null; + } final EGLTextureFrame eglTex = (EGLTextureFrame) imgTex; if(0!=eglTex.getImage()) { diff --git a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java index bc3fa0919..d3d45e692 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java +++ b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java @@ -34,6 +34,7 @@ import java.util.HashMap; import java.util.Iterator; import javax.media.opengl.GL; +import javax.media.opengl.GL2; import javax.media.opengl.GLES2; import javax.media.opengl.GLException; @@ -55,11 +56,16 @@ import com.jogamp.opengl.util.texture.TextureSequence; */ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { + protected static final String unknown = "unknown"; + protected State state; protected int textureCount; protected int textureTarget; + protected int textureFormat; + protected int textureType; 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 }; @@ -71,20 +77,24 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { protected int width = 0; /** Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */ protected int height = 0; - /** Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */ - protected int fps = 0; - /** Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */ - protected long bps = 0; + /** Video fps. Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */ + protected float fps = 0; + /** Stream bps. Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */ + protected int bps_stream = 0; + /** Video bps. Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */ + protected int bps_video = 0; + /** Audio bps. Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */ + protected int bps_audio = 0; /** In frames. Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */ - protected long totalFrames = 0; + protected int totalFrames = 0; /** In ms. Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */ - protected long duration = 0; + protected int duration = 0; /** Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */ - protected String acodec = null; + protected String acodec = unknown; /** Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */ - protected String vcodec = null; - - protected long frameNumber = 0; + protected String vcodec = unknown; + + protected int frameNumber = 0; protected TextureSequence.TextureFrame[] texFrames = null; protected HashMap<Integer, TextureSequence.TextureFrame> texFrameMap = new HashMap<Integer, TextureSequence.TextureFrame>(); @@ -93,22 +103,27 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { protected GLMediaPlayerImpl() { this.textureCount=3; this.textureTarget=GL.GL_TEXTURE_2D; + this.textureFormat = GL.GL_RGBA; + this.textureType = GL.GL_UNSIGNED_BYTE; this.texUnit = 0; this.state = State.Uninitialized; } + @Override public void setTextureUnit(int u) { texUnit = u; } + + @Override public int getTextureUnit() { return texUnit; } protected final void setTextureCount(int textureCount) { this.textureCount=textureCount; } + @Override public final int getTextureCount() { return textureCount; } - protected final void setTextureTarget(int textureTarget) { - this.textureTarget=textureTarget; - } - public final int getTextureTarget() { return textureTarget; } + protected final void setTextureTarget(int target) { textureTarget=target; } + protected final void setTextureFormat(int f) { textureFormat=f; } + protected final void setTextureType(int t) { textureType=t; } public final void setTextureMinMagFilter(int[] minMagFilter) { texMinMagFilter[0] = minMagFilter[0]; texMinMagFilter[1] = minMagFilter[1];} public final int[] getTextureMinMagFilter() { return texMinMagFilter; } @@ -116,6 +131,98 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { public final void setTextureWrapST(int[] wrapST) { texWrapST[0] = wrapST[0]; texWrapST[1] = wrapST[1];} public final int[] getTextureWrapST() { return texWrapST; } + @Override + public final TextureSequence.TextureFrame getLastTexture() throws IllegalStateException { + if(State.Uninitialized == state) { + throw new IllegalStateException("Instance not initialized: "+this); + } + return getLastTextureImpl(); + } + protected abstract TextureSequence.TextureFrame getLastTextureImpl(); + + @Override + public final synchronized TextureSequence.TextureFrame getNextTexture(GL gl, boolean blocking) throws IllegalStateException { + if(State.Uninitialized == state) { + throw new IllegalStateException("Instance not initialized: "+this); + } + if(State.Playing == state) { + final TextureSequence.TextureFrame f = getNextTextureImpl(gl, blocking); + return f; + } + return getLastTextureImpl(); + } + protected abstract TextureSequence.TextureFrame getNextTextureImpl(GL gl, boolean blocking); + + @Override + public String getRequiredExtensionsShaderStub() throws IllegalStateException { + if(State.Uninitialized == state) { + throw new IllegalStateException("Instance not initialized: "+this); + } + if(GLES2.GL_TEXTURE_EXTERNAL_OES == textureTarget) { + return TextureSequence.GL_OES_EGL_image_external_Required_Prelude; + } + return ""; + } + + @Override + public String getTextureSampler2DType() throws IllegalStateException { + if(State.Uninitialized == state) { + throw new IllegalStateException("Instance not initialized: "+this); + } + switch(textureTarget) { + case GL.GL_TEXTURE_2D: + case GL2.GL_TEXTURE_RECTANGLE: + return TextureSequence.sampler2D; + case GLES2.GL_TEXTURE_EXTERNAL_OES: + return TextureSequence.samplerExternalOES; + default: + throw new GLException("Unsuported texture target: "+toHexString(textureTarget)); + } + } + + /** + * {@inheritDoc} + * + * This implementation simply returns the build-in function name of <code>texture2D</code>, + * if not overridden by specialization. + */ + @Override + public String getTextureLookupFunctionName(String desiredFuncName) throws IllegalStateException { + if(State.Uninitialized == state) { + throw new IllegalStateException("Instance not initialized: "+this); + } + return "texture2D"; + } + + /** + * {@inheritDoc} + * + * This implementation simply returns an empty string since it's using + * the build-in function <code>texture2D</code>, + * if not overridden by specialization. + */ + @Override + public String getTextureLookupFragmentShaderImpl() throws IllegalStateException { + if(State.Uninitialized == state) { + throw new IllegalStateException("Instance not initialized: "+this); + } + return ""; + } + + @Override + public final synchronized float getPlaySpeed() { + return playSpeed; + } + + @Override + public final synchronized void setPlaySpeed(float rate) { + if(State.Uninitialized != state && setPlaySpeedImpl(rate)) { + playSpeed = rate; + } + if(DEBUG) { System.err.println("SetPlaySpeed: "+toString()); } + } + protected abstract boolean setPlaySpeedImpl(float rate); + public final State start() { switch(state) { case Stopped: @@ -124,6 +231,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { state = State.Playing; } } + if(DEBUG) { System.err.println("Start: "+toString()); } return state; } protected abstract boolean startImpl(); @@ -132,6 +240,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { if(State.Playing == state && pauseImpl()) { state = State.Paused; } + if(DEBUG) { System.err.println("Pause: "+toString()); } return state; } protected abstract boolean pauseImpl(); @@ -144,12 +253,22 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { state = State.Stopped; } } + if(DEBUG) { System.err.println("Stop: "+toString()); } return state; } protected abstract boolean stopImpl(); - public final long seek(long msec) { - final long cp; + @Override + public final int getCurrentPosition() { + if(State.Uninitialized != state) { + return getCurrentPositionImpl(); + } + return 0; + } + protected abstract int getCurrentPositionImpl(); + + public final int seek(int msec) { + final int cp; switch(state) { case Stopped: case Playing: @@ -159,14 +278,15 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { default: cp = 0; } + if(DEBUG) { System.err.println("Seek("+msec+"): "+toString()); } return cp; } - protected abstract long seekImpl(long msec); + protected abstract int seekImpl(int msec); public final State getState() { return state; } @Override - public State initGLStream(GL gl, URLConnection urlConn) throws IllegalStateException, GLException, IOException { + public final 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); } @@ -212,7 +332,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { * @see #width * @see #height * @see #fps - * @see #bps + * @see #bps_stream * @see #totalFrames * @see #acodec * @see #vcodec @@ -220,13 +340,14 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { protected abstract void initGLStreamImpl(GL gl, int[] texNames) throws IOException; protected TextureSequence.TextureFrame createTexImage(GL gl, int idx, int[] tex) { - return new TextureSequence.TextureFrame( createTexImageImpl(gl, idx, tex, false) ); + return new TextureSequence.TextureFrame( createTexImageImpl(gl, idx, tex, width, height, false) ); } - protected Texture createTexImageImpl(GL gl, int idx, int[] tex, boolean mustFlipVertically) { + protected Texture createTexImageImpl(GL gl, int idx, int[] tex, int tWidth, int tHeight, boolean mustFlipVertically) { if( 0 > tex[idx] ) { throw new RuntimeException("TextureName "+toHexString(tex[idx])+" invalid."); } + gl.glActiveTexture(GL.GL_TEXTURE0+getTextureUnit()); gl.glBindTexture(textureTarget, tex[idx]); { final int err = gl.glGetError(); @@ -241,18 +362,22 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { textureTarget, // target 0, // level GL.GL_RGBA, // internal format - width, // width - height, // height + tWidth, // width + tHeight, // height 0, // border - GL.GL_RGBA, // format - GL.GL_UNSIGNED_BYTE, // type + textureFormat, + textureType, 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)); + throw new RuntimeException("Couldn't create TexImage2D RGBA "+tWidth+"x"+tHeight+", err "+toHexString(err)); } } + if(DEBUG) { + System.err.println("Created TexImage2D RGBA "+tWidth+"x"+tHeight+", target "+toHexString(textureTarget)+ + ", ifmt "+toHexString(GL.GL_RGBA)+", fmt "+toHexString(textureFormat)+", type "+toHexString(textureType)); + } } gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MIN_FILTER, texMinMagFilter[0]); gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MAG_FILTER, texMinMagFilter[1]); @@ -261,8 +386,8 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { return com.jogamp.opengl.util.texture.TextureIO.newTexture(tex[idx], textureTarget, - width, height, - width, height, + tWidth, tHeight, + width, height, mustFlipVertically); } @@ -283,14 +408,52 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { texFrameMap.clear(); } - protected void attributesUpdated(int event_mask) { + protected final void updateAttributes(int width, int height, int bps_stream, int bps_video, int bps_audio, + float fps, int totalFrames, int duration, + String vcodec, String acodec) { + int event_mask = 0; + if( this.width != width || this.height != height ) { + event_mask |= GLMediaEventListener.EVENT_CHANGE_SIZE; + this.width = width; + this.height = height; + } + if( this.fps != fps ) { + event_mask |= GLMediaEventListener.EVENT_CHANGE_FPS; + this.fps = fps; + } + if( this.bps_stream != bps_stream || this.bps_video != bps_video || this.bps_audio != bps_audio ) { + event_mask |= GLMediaEventListener.EVENT_CHANGE_BPS; + this.bps_stream = bps_stream; + this.bps_video = bps_video; + this.bps_audio = bps_audio; + } + if( this.totalFrames != totalFrames || this.duration != duration ) { + event_mask |= GLMediaEventListener.EVENT_CHANGE_LENGTH; + this.totalFrames = totalFrames; + this.duration = duration; + } + if( (null!=acodec && acodec.length()>0 && !this.acodec.equals(acodec)) ) { + event_mask |= GLMediaEventListener.EVENT_CHANGE_CODEC; + this.acodec = acodec; + } + if( (null!=vcodec && vcodec.length()>0 && !this.vcodec.equals(vcodec)) ) { + event_mask |= GLMediaEventListener.EVENT_CHANGE_CODEC; + this.vcodec = vcodec; + } + if(0==event_mask) { + return; + } + attributesUpdated(event_mask); + } + + protected final void attributesUpdated(int event_mask) { synchronized(eventListenersLock) { for(Iterator<GLMediaEventListener> i = eventListeners.iterator(); i.hasNext(); ) { i.next().attributesChanges(this, event_mask, System.currentTimeMillis()); } } } - protected void newFrameAvailable() { + protected final void newFrameAvailable() { frameNumber++; synchronized(eventListenersLock) { for(Iterator<GLMediaEventListener> i = eventListeners.iterator(); i.hasNext(); ) { @@ -300,12 +463,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { } @Override - public synchronized float getPlaySpeed() { - return playSpeed; - } - - @Override - public synchronized State destroy(GL gl) { + public final synchronized State destroy(GL gl) { destroyImpl(gl); removeAllImageTextures(gl); state = State.Uninitialized; @@ -314,59 +472,72 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { protected abstract void destroyImpl(GL gl); @Override - public synchronized URLConnection getURLConnection() { + public final synchronized URLConnection getURLConnection() { return urlConn; } @Override - public synchronized String getVideoCodec() { + public final synchronized String getVideoCodec() { return vcodec; } @Override - public synchronized String getAudioCodec() { + public final synchronized String getAudioCodec() { return acodec; } @Override - public synchronized long getTotalFrames() { + public final synchronized long getTotalFrames() { return totalFrames; } @Override - public synchronized long getDuration() { + public final synchronized int getDuration() { return duration; } @Override - public synchronized long getBitrate() { - return bps; + public final synchronized long getStreamBitrate() { + return bps_stream; } @Override - public synchronized int getFramerate() { + public final synchronized int getVideoBitrate() { + return bps_video; + } + + @Override + public final synchronized int getAudioBitrate() { + return bps_audio; + } + + @Override + public final synchronized float getFramerate() { return fps; } @Override - public synchronized int getWidth() { + public final synchronized int getWidth() { return width; } @Override - public synchronized int getHeight() { + public final synchronized int getHeight() { return height; } @Override - public synchronized String toString() { + public final synchronized String toString() { final float ct = getCurrentPosition() / 1000.0f, tt = getDuration() / 1000.0f; 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+"]]"; + return "GLMediaPlayer["+state+", "+frameNumber+"/"+totalFrames+" frames, "+ct+"/"+tt+"s, speed "+playSpeed+", "+bps_stream+" bps, "+ + "Texture[count "+textureCount+", target "+toHexString(textureTarget)+", format "+toHexString(textureFormat)+", type "+toHexString(textureType)+"], "+ + "Stream[Video[<"+vcodec+">, "+width+"x"+height+", "+fps+" fps, "+bps_video+" bsp], "+ + "Audio[<"+acodec+">, "+bps_audio+" bsp]], "+loc+"]"; } @Override - public void addEventListener(GLMediaEventListener l) { + public final void addEventListener(GLMediaEventListener l) { if(l == null) { return; } @@ -376,7 +547,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { } @Override - public void removeEventListener(GLMediaEventListener l) { + public final void removeEventListener(GLMediaEventListener l) { if (l == null) { return; } @@ -386,7 +557,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { } @Override - public synchronized GLMediaEventListener[] getEventListeners() { + public final synchronized GLMediaEventListener[] getEventListeners() { synchronized(eventListenersLock) { return eventListeners.toArray(new GLMediaEventListener[eventListeners.size()]); } diff --git a/src/jogl/classes/jogamp/opengl/util/av/NullGLMediaPlayer.java b/src/jogl/classes/jogamp/opengl/util/av/NullGLMediaPlayer.java index c97f04225..fe2aeaf19 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/NullGLMediaPlayer.java +++ b/src/jogl/classes/jogamp/opengl/util/av/NullGLMediaPlayer.java @@ -49,8 +49,8 @@ import com.jogamp.opengl.util.texture.TextureSequence; public class NullGLMediaPlayer extends GLMediaPlayerImpl { private TextureData texData = null; private TextureSequence.TextureFrame frame = null; - private long pos_ms = 0; - private long pos_start = 0; + private int pos_ms = 0; + private int pos_start = 0; public NullGLMediaPlayer() { super(); @@ -58,18 +58,13 @@ public class NullGLMediaPlayer extends GLMediaPlayerImpl { } @Override - public void setPlaySpeed(float rate) { - // n/a + protected boolean setPlaySpeedImpl(float rate) { + return false; } @Override - public float getPlaySpeed() { - return 0; - } - - @Override protected boolean startImpl() { - pos_start = System.currentTimeMillis(); + pos_start = (int)System.currentTimeMillis(); return true; } @@ -84,25 +79,25 @@ public class NullGLMediaPlayer extends GLMediaPlayerImpl { } @Override - protected long seekImpl(long msec) { + protected int seekImpl(int msec) { pos_ms = msec; validatePos(); return pos_ms; } @Override - public TextureSequence.TextureFrame getLastTexture() { + protected TextureSequence.TextureFrame getLastTextureImpl() { return frame; } @Override - public TextureSequence.TextureFrame getNextTexture(GL gl, boolean blocking) { + protected TextureSequence.TextureFrame getNextTextureImpl(GL gl, boolean blocking) { return frame; } @Override - public long getCurrentPosition() { - pos_ms = System.currentTimeMillis() - pos_start; + protected int getCurrentPositionImpl() { + pos_ms = (int)System.currentTimeMillis() - pos_start; validatePos(); return pos_ms; } @@ -137,17 +132,15 @@ public class NullGLMediaPlayer extends GLMediaPlayerImpl { GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, false, false, false, buffer, null); } - fps = 30; - bps = 0; - totalFrames = 0; - duration = 10*60*1000; - acodec = "none"; - vcodec = "tga-dummy"; + fps = 24f; + duration = 10*60*1000; // msec + totalFrames = (int) ( (duration/1000)*fps ); + vcodec = "png-static"; } @Override protected TextureSequence.TextureFrame createTexImage(GL gl, int idx, int[] tex) { - Texture texture = super.createTexImageImpl(gl, idx, tex, false); + Texture texture = super.createTexImageImpl(gl, idx, tex, width, height, false); if(null != texData) { texture.updateImage(gl, texData); texData.destroy(); diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java b/src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java index ebbdf252f..7c812ce1c 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java +++ b/src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java @@ -6,6 +6,7 @@ import java.net.URL; import javax.media.opengl.GL; import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; import com.jogamp.opengl.util.texture.TextureSequence; @@ -13,22 +14,25 @@ import jogamp.opengl.egl.EGL; import jogamp.opengl.util.av.EGLMediaPlayerImpl; public class OMXGLMediaPlayer extends EGLMediaPlayerImpl { + static final boolean available; + + static { + // OMX binding is included in jogl_desktop and jogl_mobile + GLProfile.initSingleton(); + available = initIDs0(); + } + + public static final boolean isAvailable() { return available; } + protected long moviePtr = 0; - /** - * Old stream values, before the last attributesUpdated) - */ - protected int o_width = 0; - protected int o_height = 0; - protected int o_fps = 0; - protected long o_bps = 0; - protected long o_totalFrames = 0; - protected long o_duration = 0; - protected TextureSequence.TextureFrame lastTex = null; public OMXGLMediaPlayer() { super(TextureType.KHRImage, true); + if(!available) { + throw new RuntimeException("OMXGLMediaPlayer not available"); + } initOMX(); } @@ -80,20 +84,17 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl { } @Override - public synchronized long getCurrentPosition() { - if(0==moviePtr) { - throw new GLException("OMX native instance null"); - } - return _getCurrentPosition(moviePtr); + protected int getCurrentPositionImpl() { + return 0!=moviePtr ? _getCurrentPosition(moviePtr) : 0; } @Override - public synchronized void setPlaySpeed(float rate) { + protected boolean setPlaySpeedImpl(float rate) { if(0==moviePtr) { throw new GLException("OMX native instance null"); } _setPlaySpeed(moviePtr, rate); - playSpeed = rate; + return true; } @Override @@ -127,7 +128,7 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl { /** @return time position after issuing the command */ @Override - protected long seekImpl(long msec) { + protected int seekImpl(int msec) { if(0==moviePtr) { throw new GLException("OMX native instance null"); } @@ -135,12 +136,12 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl { } @Override - public TextureSequence.TextureFrame getLastTexture() { + protected TextureSequence.TextureFrame getLastTextureImpl() { return lastTex; } @Override - public synchronized TextureSequence.TextureFrame getNextTexture(GL gl, boolean blocking) { + protected TextureSequence.TextureFrame getNextTextureImpl(GL gl, boolean blocking) { if(0==moviePtr) { throw new GLException("OMX native instance null"); } @@ -154,38 +155,6 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl { return lastTex; } - protected void attributesUpdated() { - int event_mask = 0; - if( o_width != width || o_height != height ) { - event_mask |= GLMediaEventListener.EVENT_CHANGE_SIZE; - } - if( o_fps != fps ) { - event_mask |= GLMediaEventListener.EVENT_CHANGE_FPS; - } - if( o_bps != bps ) { - event_mask |= GLMediaEventListener.EVENT_CHANGE_BPS; - } - if( o_totalFrames != totalFrames ) { - event_mask |= GLMediaEventListener.EVENT_CHANGE_LENGTH; - } - if(0==event_mask) { - return; - } - super.attributesUpdated(event_mask); - } - - /** - * Java callback method issued by the native OMX backend - */ - private void saveAttributes() { - o_width = width; - o_height = height; - o_fps = fps; - o_bps = bps; - o_totalFrames = totalFrames; - o_duration = duration; - } - private String replaceAll(String orig, String search, String repl) { String dest=null; // In case replaceAll / java.util.regex.* is not supported (-> CVM) @@ -206,21 +175,22 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl { } } - native long _createInstance(); - native void _destroyInstance(long moviePtr); + private static native boolean initIDs0(); + private native long _createInstance(); + private native void _destroyInstance(long moviePtr); - native void _detachVideoRenderer(long moviePtr); // stop before - native void _attachVideoRenderer(long moviePtr); // detach before - native void _setStream(long moviePtr, int textureNum, String path); - native void _activateStream(long moviePtr); + private native void _detachVideoRenderer(long moviePtr); // stop before + private native void _attachVideoRenderer(long moviePtr); // detach before + private native void _setStream(long moviePtr, int textureNum, String path); + private native void _activateStream(long moviePtr); - native void _setStreamEGLImageTexture2D(long moviePtr, int i, int tex, long image, long sync); - 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, boolean blocking); - native long _getCurrentPosition(long moviePtr); + private native void _setStreamEGLImageTexture2D(long moviePtr, int i, int tex, long image, long sync); + private native int _seek(long moviePtr, int position); + private native void _setPlaySpeed(long moviePtr, float rate); + private native void _play(long moviePtr); + private native void _pause(long moviePtr); + private native void _stop(long moviePtr); + private native int _getNextTextureID(long moviePtr, boolean blocking); + private native int _getCurrentPosition(long moviePtr); } |