aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2012-04-16 21:18:03 +0200
committerSven Gothel <[email protected]>2012-04-16 21:18:03 +0200
commit35beeabffed61e1597aaffc0c5926ab5ef86d32e (patch)
tree6a7e91c07e7d61613b03f35a17486faf01b211fc /src/jogl
parent2f0583aad39f93a934629c21beac66a758373249 (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')
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java44
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java153
-rw-r--r--src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java44
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java58
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java273
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/NullGLMediaPlayer.java37
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java102
-rw-r--r--src/jogl/native/JoglCommon.c56
-rw-r--r--src/jogl/native/JoglCommon.h3
-rw-r--r--src/jogl/native/openmax/jogamp_opengl_util_av_impl_OMXGLMediaPlayer.c124
-rw-r--r--src/jogl/native/openmax/omx_tool.c123
-rw-r--r--src/jogl/native/openmax/omx_tool.h20
12 files changed, 652 insertions, 385 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java
index d86c8bfd0..8430d6137 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java
@@ -47,6 +47,15 @@ import com.jogamp.opengl.util.texture.TextureSequence;
* <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>
+ * <p>
+ * Variable type, value range and dimension has been chosen to suit embedded CPUs
+ * and characteristics of audio and video streaming.
+ * Milliseconds of type integer with a maximum value of {@link Integer#MAX_VALUE}
+ * will allow tracking time up 2,147,483.647 seconds or
+ * 24 days 20 hours 31 minutes and 23 seconds.
+ * Milliseconds granularity is also more than enough to deal with A-V synchronization,
+ * where the threshold usually lies within 100ms.
+ * </p>
*/
public interface GLMediaPlayer extends TextureSequence {
public static final boolean DEBUG = Debug.debug("GLMediaPlayer");
@@ -57,6 +66,7 @@ public interface GLMediaPlayer extends TextureSequence {
static final int EVENT_CHANGE_FPS = 1<<1;
static final int EVENT_CHANGE_BPS = 1<<2;
static final int EVENT_CHANGE_LENGTH = 1<<3;
+ static final int EVENT_CHANGE_CODEC = 1<<3;
/**
* @param mp the event source
@@ -136,7 +146,7 @@ public interface GLMediaPlayer extends TextureSequence {
/**
* @return time current position in milliseconds
**/
- public long getCurrentPosition();
+ public int getCurrentPosition();
/**
* Allowed in state Stopped, Playing and Paused, otherwise ignored.
@@ -144,20 +154,26 @@ public interface GLMediaPlayer extends TextureSequence {
* @param msec absolute desired time position in milliseconds
* @return time current position in milliseconds, after seeking to the desired position
**/
- public long seek(long msec);
+ public int seek(int msec);
/**
* {@inheritDoc}
*/
- public TextureSequence.TextureFrame getLastTexture();
+ @Override
+ public TextureSequence.TextureFrame getLastTexture() throws IllegalStateException;
/**
* {@inheritDoc}
*
+ * <p>
+ * In case the current state is not {@link State#Playing}, {@link #getLastTexture()} is returned.
+ * </p>
+ *
* @see #addEventListener(GLMediaEventListener)
* @see GLMediaEventListener#newFrameAvailable(GLMediaPlayer, long)
*/
- public TextureSequence.TextureFrame getNextTexture(GL gl, boolean blocking);
+ @Override
+ public TextureSequence.TextureFrame getNextTexture(GL gl, boolean blocking) throws IllegalStateException;
public URLConnection getURLConnection();
@@ -182,19 +198,31 @@ public interface GLMediaPlayer extends TextureSequence {
/**
* @return total duration of stream in msec.
*/
- public long getDuration();
+ public int getDuration();
/**
* <i>Warning:</i> Optional information, may not be supported by implementation.
* @return the overall bitrate of the stream.
*/
- public long getBitrate();
+ public long getStreamBitrate();
/**
* <i>Warning:</i> Optional information, may not be supported by implementation.
+ * @return video bitrate
+ */
+ public int getVideoBitrate();
+
+ /**
+ * <i>Warning:</i> Optional information, may not be supported by implementation.
+ * @return the audio bitrate
+ */
+ public int getAudioBitrate();
+
+ /**
+ * <i>Warning:</i> Optional information, may not be supported by implementation.
* @return the framerate of the video
*/
- public int getFramerate();
+ public float getFramerate();
public int getWidth();
@@ -207,5 +235,5 @@ public interface GLMediaPlayer extends TextureSequence {
public void removeEventListener(GLMediaEventListener l);
public GLMediaEventListener[] getEventListeners();
-
+
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java
index e6d21c613..5ee2104a3 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java
@@ -29,23 +29,98 @@ package com.jogamp.opengl.util.texture;
import javax.media.opengl.GL;
+/**
+ * Protocol for texture sequences, like animations, movies, etc.
+ * <p>
+ * Ensure to respect the texture coordinates provided by
+ * {@link TextureFrame}.{@link TextureFrame#getTexture() getTexture()}.{@link Texture#getImageTexCoords() getImageTexCoords()}.
+ * </p>
+ * The user's shader shall be fitted for this implementation.
+ * Assuming we use a base shader code w/o headers using </code>ShaderCode</code>.
+ * (Code copied from unit test / demo <code>TexCubeES2</code>)
+ * <pre>
+ *
+ static final String[] es2_prelude = { "#version 100\n", "precision mediump float;\n" };
+ static final String gl2_prelude = "#version 110\n";
+ static final String shaderBasename = "texsequence_xxx"; // the base shader code w/o headers
+ static final String myTextureLookupName = "myTexture2D"; // the desired texture lookup function
+
+ private void initShader(GL2ES2 gl, TextureSequence texSeq) {
+ // Create & Compile the shader objects
+ ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, TexCubeES2.class,
+ "shader", "shader/bin", shaderBasename, true);
+ ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, TexCubeES2.class,
+ "shader", "shader/bin", shaderBasename, true);
+
+ // Prelude shader code w/ GLSL profile specifics [ 1. pre-proc, 2. other ]
+ int rsFpPos;
+ if(gl.isGLES2()) {
+ // insert ES2 version string in beginning
+ rsVp.insertShaderSource(0, 0, es2_prelude[0]);
+ rsFpPos = rsFp.insertShaderSource(0, 0, es2_prelude[0]);
+ } else {
+ // insert GL2 version string in beginning
+ rsVp.insertShaderSource(0, 0, gl2_prelude);
+ rsFpPos = rsFp.insertShaderSource(0, 0, gl2_prelude);
+ }
+ // insert required extensions as determined by TextureSequence implementation.
+ rsFpPos = rsFp.insertShaderSource(0, rsFpPos, texSeq.getRequiredExtensionsShaderStub());
+ if(gl.isGLES2()) {
+ // insert ES2 default precision declaration
+ rsFpPos = rsFp.insertShaderSource(0, rsFpPos, es2_prelude[1]);
+ }
+ // negotiate the texture lookup function name
+ final String texLookupFuncName = texSeq.getTextureLookupFunctionName(myTextureLookupName);
+
+ // in case a fixed lookup function is being chosen, replace the name in our code
+ rsFp.replaceInShaderSource(myTextureLookupName, texLookupFuncName);
+
+ // Cache the TextureSequence shader details in StringBuffer:
+ final StringBuilder sFpIns = new StringBuilder();
+
+ // .. declaration of the texture sampler using the implementation specific type
+ sFpIns.append("uniform ").append(texSeq.getTextureSampler2DType()).append(" mgl_ActiveTexture;\n");
+
+ // .. the actual texture lookup function, maybe null in case a built-in function is being used
+ sFpIns.append(texSeq.getTextureLookupFragmentShaderImpl());
+
+ // Now insert the TextureShader details in our shader after the given tag:
+ rsFp.insertShaderSource(0, "TEXTURE-SEQUENCE-CODE-BEGIN", 0, sFpIns);
+
+ // Create & Link the shader program
+ ShaderProgram sp = new ShaderProgram();
+ sp.add(rsVp);
+ sp.add(rsFp);
+ if(!sp.link(gl, System.err)) {
+ throw new GLException("Couldn't link program: "+sp);
+ }
+ ...
+ * </pre>
+ * The above procedure might look complicated, however, it allows most flexibility and
+ * workarounds to also deal with GLSL bugs.
+ *
+ */
public interface TextureSequence {
-
+ public static final String GL_OES_EGL_image_external_Required_Prelude = "#extension GL_OES_EGL_image_external : enable\n";
+ public static final String GL_OES_EGL_image_external = "GL_OES_EGL_image_external";
+ public static final String samplerExternalOES = "samplerExternalOES";
+ public static final String sampler2D = "sampler2D";
+
+ /**
+ * Texture holder interface, maybe specialized by implementation
+ * to associated related data.
+ */
public static class TextureFrame {
public TextureFrame(Texture t) {
texture = t;
- // stMatrix = new float[4*4];
- // ProjectFloat.makeIdentityf(stMatrix, 0);
}
public final Texture getTexture() { return texture; }
- // public final float[] getSTMatrix() { return stMatrix; }
public String toString() {
return "TextureFrame[" + texture + "]";
}
protected final Texture texture;
- // protected final float[] stMatrix;
}
public interface TexSeqEventListener<T extends TextureSequence> {
@@ -57,8 +132,7 @@ public interface TextureSequence {
public void newFrameAvailable(T ts, long when);
}
- public int getTextureTarget();
-
+ /** Return the texture unit to be used with this frame. */
public int getTextureUnit();
public int[] getTextureMinMagFilter();
@@ -66,15 +140,17 @@ public interface TextureSequence {
public int[] getTextureWrapST();
/**
- * Returns the last updated texture.
+ * Returns the last updated texture.
* <p>
* In case the instance is just initialized, it shall return a <code>TextureFrame</code>
* object with valid attributes. The texture content may be undefined
* until the first call of {@link #getNextTexture(GL, boolean)}.<br>
* </p>
- * Not blocking.
+ * Not blocking.
+ *
+ * @throws IllegalStateException if instance is not initialized
*/
- public TextureFrame getLastTexture();
+ public TextureFrame getLastTexture() throws IllegalStateException ;
/**
* Returns the next texture to be rendered.
@@ -85,6 +161,61 @@ public interface TextureSequence {
* <p>
* Shall return <code>null</code> in case <i>no</i> frame is available.
* </p>
+ *
+ * @throws IllegalStateException if instance is not initialized
+ */
+ public TextureFrame getNextTexture(GL gl, boolean blocking) throws IllegalStateException ;
+
+ /**
+ * In case a shader extension is required, based on the implementation
+ * and the runtime GL profile, this method returns the preprocessor macros, e.g.:
+ * <pre>
+ * #extension GL_OES_EGL_image_external : enable
+ * </pre>
+ *
+ * @throws IllegalStateException if instance is not initialized
+ */
+ public String getRequiredExtensionsShaderStub() throws IllegalStateException ;
+
+ /**
+ * Returns either <code>sampler2D</code> or <code>samplerExternalOES</code>
+ * depending on {@link #getLastTexture()}.{@link TextureFrame#getTexture() getTexture()}.{@link Texture#getTarget() getTarget()}.
+ *
+ * @throws IllegalStateException if instance is not initialized
+ **/
+ public String getTextureSampler2DType() throws IllegalStateException ;
+
+ /**
+ * @param desiredFuncName desired lookup function name. If <code>null</code> or ignored by the implementation,
+ * a build-in name is returned.
+ * @return the final lookup function name
+ *
+ * @see {@link #getTextureLookupFragmentShaderImpl()}
+ *
+ * @throws IllegalStateException if instance is not initialized
+ */
+ public String getTextureLookupFunctionName(String desiredFuncName) throws IllegalStateException ;
+
+ /**
+ * Returns the complete texture2D lookup function code of type
+ * <pre>
+ * vec4 <i>funcName</i>(in <i>getTextureSampler2DType()</i> image, in vec2 texCoord) {
+ * vec4 texColor = do_something_with(image, texCoord);
+ * return texColor;
+ * }
+ * </pre>
+ * <p>
+ * <i>funcName</i> can be negotiated and queried via {@link #getTextureLookupFunctionName(String)}.
+ * </p>
+ * Note: This function may return an empty string in case a build-in lookup
+ * function is being chosen. If the implementation desires so,
+ * {@link #getTextureLookupFunctionName(String)} will ignore the desired function name
+ * and returns the build-in lookup function name.
+ * </p>
+ * @see #getTextureLookupFunctionName(String)
+ * @see #getTextureSampler2DType()
+ *
+ * @throws IllegalStateException if instance is not initialized
*/
- public TextureFrame getNextTexture(GL gl, boolean blocking);
+ public String getTextureLookupFragmentShaderImpl() throws IllegalStateException ;
} \ No newline at end of file
diff --git a/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java b/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java
index 1239db742..f6189f03c 100644
--- a/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java
+++ b/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java
@@ -48,6 +48,14 @@ import android.view.Surface;
* Android API Level 14: {@link Surface#Surface(android.graphics.SurfaceTexture)}
*/
public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl {
+ static final boolean available;
+
+ static {
+ available = true; // default .. TODO: May restrict availability ?
+ }
+
+ public static final boolean isAvailable() { return available; }
+
MediaPlayer mp;
volatile boolean updateSurface = false;
Object updateSurfaceLock = new Object();
@@ -61,22 +69,20 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl {
public AndroidGLMediaPlayerAPI14() {
super();
+ if(!available) {
+ throw new RuntimeException("AndroidGLMediaPlayerAPI14 not available");
+ }
this.setTextureTarget(GLES2.GL_TEXTURE_EXTERNAL_OES);
this.setTextureCount(1);
mp = new MediaPlayer();
}
@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() {
if(null != mp) {
try {
@@ -124,21 +130,21 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl {
}
@Override
- protected long seekImpl(long msec) {
+ protected int seekImpl(int msec) {
if(null != mp) {
- mp.seekTo((int)msec);
+ mp.seekTo(msec);
return mp.getCurrentPosition();
}
return 0;
}
@Override
- public TextureSequence.TextureFrame getLastTexture() {
+ protected TextureSequence.TextureFrame getLastTextureImpl() {
return lastTexFrame;
}
@Override
- public TextureSequence.TextureFrame getNextTexture(GL gl, boolean blocking) {
+ protected TextureSequence.TextureFrame getNextTextureImpl(GL gl, boolean blocking) {
if(null != stex && null != mp) {
// Only block once, no while-loop.
// This relaxes locking code of non crucial resources/events.
@@ -176,7 +182,7 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl {
}
@Override
- public long getCurrentPosition() {
+ protected int getCurrentPositionImpl() {
return null != mp ? mp.getCurrentPosition() : 0;
}
@@ -214,20 +220,16 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl {
} 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;
- bps = 0;
- totalFrames = 0;
- duration = mp.getDuration();
- acodec = "unknown";
- vcodec = "unknown";
+ updateAttributes(mp.getVideoWidth(), mp.getVideoHeight(),
+ 0, 0, 0,
+ 0f, 0, mp.getDuration(),
+ null, null);
}
}
@Override
protected TextureSequence.TextureFrame createTexImage(GL gl, int idx, int[] tex) {
- lastTexFrame = new TextureSequence.TextureFrame( createTexImageImpl(gl, idx, tex, true) );
+ lastTexFrame = new TextureSequence.TextureFrame( createTexImageImpl(gl, idx, tex, width, height, true) );
return lastTexFrame;
}
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);
}
diff --git a/src/jogl/native/JoglCommon.c b/src/jogl/native/JoglCommon.c
index 719e0df56..d9f5edd49 100644
--- a/src/jogl/native/JoglCommon.c
+++ b/src/jogl/native/JoglCommon.c
@@ -11,48 +11,63 @@ static jclass runtimeExceptionClz=NULL;
static JavaVM *_jvmHandle = NULL;
static int _jvmVersion = 0;
+void JoglCommon_init(JNIEnv *env) {
+ if(NULL==runtimeExceptionClz) {
+ jclass c = (*env)->FindClass(env, ClazzNameRuntimeException);
+ if(NULL==c) {
+ JoglCommon_FatalError(env, "JOGL: can't find %s", ClazzNameRuntimeException);
+ }
+ runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==runtimeExceptionClz) {
+ JoglCommon_FatalError(env, "JOGL: can't use %s", ClazzNameRuntimeException);
+ }
+ }
+ if(0 != (*env)->GetJavaVM(env, &_jvmHandle)) {
+ JoglCommon_FatalError(env, "JOGL: can't fetch JavaVM handle");
+ } else {
+ _jvmVersion = (*env)->GetVersion(env);
+ }
+}
void JoglCommon_FatalError(JNIEnv *env, const char* msg, ...)
{
char buffer[512];
va_list ap;
+ int shallBeDetached = 0;
+
+ if(NULL == env) {
+ env = JoglCommon_GetJNIEnv (&shallBeDetached);
+ }
va_start(ap, msg);
vsnprintf(buffer, sizeof(buffer), msg, ap);
va_end(ap);
fprintf(stderr, "%s\n", buffer);
- (*env)->FatalError(env, buffer);
+ if(NULL != env) {
+ (*env)->FatalError(env, buffer);
+ JoglCommon_ReleaseJNIEnv (shallBeDetached);
+ }
}
void JoglCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...)
{
char buffer[512];
va_list ap;
+ int shallBeDetached = 0;
+
+ if(NULL == env) {
+ env = JoglCommon_GetJNIEnv (&shallBeDetached);
+ }
va_start(ap, msg);
vsnprintf(buffer, sizeof(buffer), msg, ap);
va_end(ap);
- (*env)->ThrowNew(env, runtimeExceptionClz, buffer);
-}
-
-void JoglCommon_init(JNIEnv *env) {
- if(NULL==runtimeExceptionClz) {
- jclass c = (*env)->FindClass(env, ClazzNameRuntimeException);
- if(NULL==c) {
- JoglCommon_FatalError(env, "JOGL: can't find %s", ClazzNameRuntimeException);
- }
- runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c);
- (*env)->DeleteLocalRef(env, c);
- if(NULL==runtimeExceptionClz) {
- JoglCommon_FatalError(env, "JOGL: can't use %s", ClazzNameRuntimeException);
- }
- }
- if(0 != (*env)->GetJavaVM(env, &_jvmHandle)) {
- JoglCommon_FatalError(env, "JOGL: can't fetch JavaVM handle");
- } else {
- _jvmVersion = (*env)->GetVersion(env);
+ if(NULL != env) {
+ (*env)->ThrowNew(env, runtimeExceptionClz, buffer);
+ JoglCommon_ReleaseJNIEnv (shallBeDetached);
}
}
@@ -110,7 +125,6 @@ JNIEnv* JoglCommon_GetJNIEnv (int * shallBeDetached)
void JoglCommon_ReleaseJNIEnv (int shallBeDetached) {
if(NULL == _jvmHandle) {
fprintf(stderr, "JOGL: No JavaVM handle registered, call JoglCommon_init(..) 1st");
- return NULL;
}
if(shallBeDetached) {
diff --git a/src/jogl/native/JoglCommon.h b/src/jogl/native/JoglCommon.h
index b988336fa..023b4be03 100644
--- a/src/jogl/native/JoglCommon.h
+++ b/src/jogl/native/JoglCommon.h
@@ -15,7 +15,10 @@ int JoglCommon_GetJVMVersion();
jchar* JoglCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str);
+/** env may be NULL, in which case JoglCommon_GetJNIEnv() is being used. */
void JoglCommon_FatalError(JNIEnv *env, const char* msg, ...);
+
+/** env may be NULL, in which case JoglCommon_GetJNIEnv() is being used. */
void JoglCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...);
/**
diff --git a/src/jogl/native/openmax/jogamp_opengl_util_av_impl_OMXGLMediaPlayer.c b/src/jogl/native/openmax/jogamp_opengl_util_av_impl_OMXGLMediaPlayer.c
index 60e436678..964ac64a7 100644
--- a/src/jogl/native/openmax/jogamp_opengl_util_av_impl_OMXGLMediaPlayer.c
+++ b/src/jogl/native/openmax/jogamp_opengl_util_av_impl_OMXGLMediaPlayer.c
@@ -14,94 +14,68 @@
// http://developer.apple.com/qa/qa2001/qa1262.html
#include "jogamp_opengl_util_av_impl_OMXGLMediaPlayer.h"
+#include "JoglCommon.h"
#include "omx_tool.h"
#include <stdarg.h>
-static const char * const ClazzNameRuntimeException =
- "java/lang/RuntimeException";
-static jclass runtimeExceptionClz=NULL;
+static const char * const ClazzNameOMXGLMediaPlayer = "jogamp/opengl/util/av/impl/OMXGLMediaPlayer";
+
+static jclass omxGLMediaPlayerClazz = NULL;
+static jmethodID jni_mid_updateAttributes = NULL;
+
#ifdef _WIN32_WCE
#define STDOUT_FILE "\\Storage Card\\demos\\stdout.txt"
#define STDERR_FILE "\\Storage Card\\demos\\stderr.txt"
#endif
-static void _initStatics(JNIEnv *env)
+JNIEXPORT jboolean JNICALL Java_jogamp_opengl_util_av_impl_OMXGLMediaPlayer_initIDs0
+ (JNIEnv *env, jclass clazz)
{
- jclass c;
#ifdef _WIN32_WCE
_wfreopen(TEXT(STDOUT_FILE),L"w",stdout);
_wfreopen(TEXT(STDERR_FILE),L"w",stderr);
#endif
- fprintf(stdout, "_initstatics ..\n"); fflush(stdout); // JAU
- if (runtimeExceptionClz != NULL) {
+ JoglCommon_init(env);
+
+ jclass c;
+ if (omxGLMediaPlayerClazz != NULL) {
return;
}
- c = (*env)->FindClass(env, ClazzNameRuntimeException);
+ c = (*env)->FindClass(env, ClazzNameOMXGLMediaPlayer);
if(NULL==c) {
- fprintf(stdout, "FatalError: can't find %s\n", ClazzNameRuntimeException);
- (*env)->FatalError(env, ClazzNameRuntimeException);
+ JoglCommon_FatalError(env, "JOGL OMX: can't find %s", ClazzNameOMXGLMediaPlayer);
}
- runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c);
- if(NULL==runtimeExceptionClz) {
- fprintf(stdout, "FatalError: can't use %s\n", ClazzNameRuntimeException);
- (*env)->FatalError(env, ClazzNameRuntimeException);
+ omxGLMediaPlayerClazz = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==omxGLMediaPlayerClazz) {
+ JoglCommon_FatalError(env, "JOGL OMX: can't use %s", ClazzNameOMXGLMediaPlayer);
}
-}
-void java_throwNewRuntimeException(intptr_t jni_env, const char* format, ...)
-{
- va_list ap;
- char buffer[255];
- va_start(ap, format);
- #ifdef _WIN32
- _vsnprintf(buffer, sizeof(buffer)-1, format, ap);
- #else
- vsnprintf(buffer, sizeof(buffer)-1, format, ap);
- #endif
- va_end(ap);
- buffer[sizeof(buffer)-1]=0;
- fprintf(stderr, "RuntimeException: %s\n", buffer); fflush(stderr);
- if(jni_env!=0) {
- (*((JNIEnv *)jni_env))->ThrowNew((JNIEnv *)jni_env, runtimeExceptionClz, buffer);
- }
-}
+ jni_mid_updateAttributes = (*env)->GetMethodID(env, omxGLMediaPlayerClazz, "updateAttributes", "(IIIIIFIILjava/lang/String;Ljava/lang/String;)V");
-void OMXInstance_SaveJavaAttributes(OMXToolBasicAV_t *pOMXAV, KDboolean issueJavaCallback)
-{
- if(NULL==pOMXAV || 0==pOMXAV->jni_env || 0==pOMXAV->jni_instance) {
- fprintf(stderr, "OMXInstance_SaveJavaAttributes failed");
- return;
- } else if(issueJavaCallback==KD_TRUE) {
- JNIEnv * env = (JNIEnv *)pOMXAV->jni_env;
- jobject instance = (jobject)pOMXAV->jni_instance;
- (*env)->CallVoidMethod(env, instance, (jmethodID)pOMXAV->jni_mid_saveAttributes);
+ if(jni_mid_updateAttributes == NULL) {
+ return JNI_FALSE;
}
+ return JNI_TRUE;
}
-void OMXInstance_UpdateJavaAttributes(OMXToolBasicAV_t *pOMXAV, KDboolean issueJavaCallback)
+void OMXInstance_UpdateJavaAttributes(OMXToolBasicAV_t *pAV)
{
- if(NULL==pOMXAV || 0==pOMXAV->jni_env || 0==pOMXAV->jni_instance) {
+ if(NULL==pAV || 0==pAV->jni_instance) {
fprintf(stderr, "OMXInstance_UpdateJavaAttributes failed");
return;
- } else {
- JNIEnv * env = (JNIEnv *)pOMXAV->jni_env;
- jobject instance = (jobject)pOMXAV->jni_instance;
- (*env)->SetIntField(env, instance, (jfieldID)pOMXAV->jni_fid_width, (jint)pOMXAV->width);
- (*env)->SetIntField(env, instance, (jfieldID)pOMXAV->jni_fid_height, (jint)pOMXAV->height);
- (*env)->SetIntField(env, instance, (jfieldID)pOMXAV->jni_fid_fps, (jint)pOMXAV->framerate);
- (*env)->SetLongField(env, instance, (jfieldID)pOMXAV->jni_fid_bps, (jlong)pOMXAV->bitrate);
- (*env)->SetLongField(env, instance, (jfieldID)pOMXAV->jni_fid_totalFrames, (jlong)(pOMXAV->length*pOMXAV->framerate));
- if(issueJavaCallback==KD_TRUE) {
- (*env)->CallVoidMethod(env, instance, (jmethodID)pOMXAV->jni_mid_attributesUpdated);
- } else {
- if(strlen(pOMXAV->videoCodec)>0) {
- (*env)->SetObjectField(env, instance, (jfieldID)pOMXAV->jni_fid_vcodec, (*env)->NewStringUTF(env, pOMXAV->videoCodec));
- }
- if(strlen(pOMXAV->audioCodec)>0) {
- (*env)->SetObjectField(env, instance, (jfieldID)pOMXAV->jni_fid_acodec, (*env)->NewStringUTF(env, pOMXAV->audioCodec));
- }
- }
+ }
+ int shallBeDetached = 0;
+ JNIEnv * env = JoglCommon_GetJNIEnv (&shallBeDetached);
+ if(NULL!=env) {
+ (*env)->CallVoidMethod(env, (jobject)pAV->jni_instance, jni_mid_updateAttributes,
+ pAV->width, pAV->height,
+ pAV->bitrate, 0, 0,
+ pAV->framerate, (uint32_t)(pAV->length*pAV->framerate), pAV->length,
+ (*env)->NewStringUTF(env, pAV->videoCodec),
+ (*env)->NewStringUTF(env, pAV->audioCodec) );
+ JoglCommon_ReleaseJNIEnv (shallBeDetached);
}
}
@@ -110,26 +84,9 @@ JNIEXPORT jlong JNICALL Java_jogamp_opengl_util_av_impl_OMXGLMediaPlayer__1creat
{
OMXToolBasicAV_t * pOMXAV;
- _initStatics(env);
-
- pOMXAV->jni_env=(intptr_t)env;
- pOMXAV->jni_instance=(intptr_t)instance;
-
pOMXAV = OMXToolBasicAV_CreateInstance((EGLDisplay)(intptr_t)env);
- if(NULL!=pOMXAV) {
- jclass cls = (*env)->GetObjectClass(env, instance);
- pOMXAV->jni_mid_saveAttributes = (intptr_t) (*env)->GetMethodID(env, cls, "saveAttributes", "()V");
- pOMXAV->jni_mid_attributesUpdated = (intptr_t) (*env)->GetMethodID(env, cls, "attributesUpdated", "()V");
- pOMXAV->jni_fid_width = (intptr_t) (*env)->GetFieldID(env, cls, "width", "I");
- pOMXAV->jni_fid_height = (intptr_t) (*env)->GetFieldID(env, cls, "height", "I");
- pOMXAV->jni_fid_fps = (intptr_t) (*env)->GetFieldID(env, cls, "fps", "I");
- pOMXAV->jni_fid_bps = (intptr_t) (*env)->GetFieldID(env, cls, "bps", "J");
- pOMXAV->jni_fid_totalFrames = (intptr_t) (*env)->GetFieldID(env, cls, "totalFrames", "J");
- pOMXAV->jni_fid_acodec = (intptr_t) (*env)->GetFieldID(env, cls, "acodec", "Ljava/lang/String;");
- pOMXAV->jni_fid_vcodec = (intptr_t) (*env)->GetFieldID(env, cls, "vcodec", "Ljava/lang/String;");
- }
-
- return (jlong) (intptr_t) (void *)pOMXAV;
+ pOMXAV->jni_instance=(intptr_t)instance;
+ return (jlong) (intptr_t) pOMXAV;
}
JNIEXPORT void JNICALL Java_jogamp_opengl_util_av_impl_OMXGLMediaPlayer__1setStream
@@ -142,7 +99,6 @@ JNIEXPORT void JNICALL Java_jogamp_opengl_util_av_impl_OMXGLMediaPlayer__1setStr
if (pOMXAV != NULL) {
const char *filePath = (*env)->GetStringUTFChars(env, jpath, &iscopy);
fprintf(stdout, "setStream 2 %s..\n", filePath); fflush(stdout); // JAU
- pOMXAV->jni_env=(intptr_t)env;
pOMXAV->jni_instance=(intptr_t)instance;
OMXToolBasicAV_SetStream(pOMXAV, vBufferNum, filePath);
(*env)->ReleaseStringChars(env, jpath, (const jchar *)filePath);
@@ -213,8 +169,8 @@ JNIEXPORT void JNICALL Java_jogamp_opengl_util_av_impl_OMXGLMediaPlayer__1stop
OMXToolBasicAV_PlayStop(pOMXAV);
}
-JNIEXPORT jlong JNICALL Java_jogamp_opengl_util_av_impl_OMXGLMediaPlayer__1seek
- (JNIEnv *env, jobject instance, jlong ptr, jlong pos)
+JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_OMXGLMediaPlayer__1seek
+ (JNIEnv *env, jobject instance, jlong ptr, jint pos)
{
OMXToolBasicAV_t *pOMXAV = (OMXToolBasicAV_t *)((void *)((intptr_t)ptr));
OMXToolBasicAV_PlaySeek(pOMXAV, pos);
@@ -232,7 +188,7 @@ JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_OMXGLMediaPlayer__1getNex
return textureID;
}
-JNIEXPORT jlong JNICALL Java_jogamp_opengl_util_av_impl_OMXGLMediaPlayer__1getCurrentPosition
+JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_OMXGLMediaPlayer__1getCurrentPosition
(JNIEnv *env, jobject instance, jlong ptr)
{
OMXToolBasicAV_t *pOMXAV = (OMXToolBasicAV_t *)((void *)((intptr_t)ptr));
diff --git a/src/jogl/native/openmax/omx_tool.c b/src/jogl/native/openmax/omx_tool.c
index 5e168ad02..16c43f6a8 100644
--- a/src/jogl/native/openmax/omx_tool.c
+++ b/src/jogl/native/openmax/omx_tool.c
@@ -28,35 +28,15 @@
#define NOTSET_U32 ((OMX_U32)0xDEDEDEDE)
#define INIT_PARAM(_X_) (memset(&(_X_), NOTSET_U8, sizeof(_X_)), ((_X_).nSize = sizeof (_X_)), (_X_).nVersion = vOMX)
-void OMXInstance_SaveJavaAttributes(OMXToolBasicAV_t *pOMXAV, KDboolean issueJavaCallback);
-void OMXInstance_UpdateJavaAttributes(OMXToolBasicAV_t *pOMXAV, KDboolean issueJavaCallback);
+void OMXInstance_UpdateJavaAttributes(OMXToolBasicAV_t *pOMXAV);
-#if !defined(SELF_TEST)
-void java_throwNewRuntimeException(intptr_t jni_env, const char* format, ...);
-#else
-#include <stdarg.h>
-void java_throwNewRuntimeException(intptr_t jni_env, const char* format, ...) {
- va_list ap;
- char buffer[255];
- va_start(ap, format);
- #ifdef _WIN32
- _vsnprintf(buffer, sizeof(buffer)-1, format, ap);
- #else
- vsnprintf(buffer, sizeof(buffer)-1, format, ap);
- #endif
- va_end(ap);
- buffer[sizeof(buffer)-1]=0;
- DBG_PRINT( "RuntimeException: %s\n", buffer);
- exit(1);
-}
-#endif
static void DestroyInstanceUnlock(OMXToolBasicAV_t * pOMXAV);
#define OMXSAFEVOID(x) \
do { \
OMX_ERRORTYPE err = (x); \
if (err != OMX_ErrorNone) { \
- java_throwNewRuntimeException((NULL!=pOMXAV)?pOMXAV->jni_env:0, "FAILED at %s:%d, Error: 0x%x\n", __FILE__, __LINE__, err); \
+ JoglCommon_throwNewRuntimeException(0, "FAILED at %s:%d, Error: 0x%x\n", __FILE__, __LINE__, err); \
if(NULL!=pOMXAV) { \
DestroyInstanceUnlock(pOMXAV); \
} \
@@ -68,7 +48,7 @@ do { \
do { \
OMX_ERRORTYPE err = (x); \
if (err != OMX_ErrorNone) { \
- java_throwNewRuntimeException((NULL!=pOMXAV)?pOMXAV->jni_env:0, "FAILED at %s:%d, Error: 0x%x\n", __FILE__, __LINE__, err); \
+ JoglCommon_throwNewRuntimeException(0, "FAILED at %s:%d, Error: 0x%x\n", __FILE__, __LINE__, err); \
if(NULL!=pOMXAV) { \
DestroyInstanceUnlock(pOMXAV); \
} \
@@ -80,7 +60,7 @@ do { \
do { \
OMX_ERRORTYPE err = (x); \
if (err != OMX_ErrorNone) { \
- java_throwNewRuntimeException((NULL!=pOMXAV)?pOMXAV->jni_env:0, "FAILED at %s:%d, Error: 0x%x\n", __FILE__, __LINE__, err); \
+ JoglCommon_throwNewRuntimeException(0, "FAILED at %s:%d, Error: 0x%x\n", __FILE__, __LINE__, err); \
if(NULL!=pOMXAV) { \
DestroyInstanceUnlock(pOMXAV); \
} \
@@ -466,7 +446,7 @@ static void DestroyInstanceUnlock(OMXToolBasicAV_t * pOMXAV)
DBG_PRINT( "Destroy p2\n");
if(0!=(res1=OMXToolBasicAV_RequestState(pOMXAV, OMX_StateIdle, KD_TRUE)))
{
- java_throwNewRuntimeException(pOMXAV->jni_env, "Destroy - Wait for Idle Failed (%d)", res1);
+ JoglCommon_throwNewRuntimeException(0, "Destroy - Wait for Idle Failed (%d)", res1);
}
DBG_PRINT( "Destroy p3\n");
@@ -479,7 +459,7 @@ static void DestroyInstanceUnlock(OMXToolBasicAV_t * pOMXAV)
if(0!=(res2=OMXToolBasicAV_RequestState(pOMXAV, OMX_StateLoaded, KD_TRUE)))
{
if(!res1) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "Destroy - Wait for Loaded Failed (%d)", res2);
+ JoglCommon_throwNewRuntimeException(0, "Destroy - Wait for Loaded Failed (%d)", res2);
}
}
@@ -726,19 +706,20 @@ static OMX_ERRORTYPE UpdateStreamInfo(OMXToolBasicAV_t * pOMXAV, KDboolean issue
}
DBG_PRINT( "Update StreamInfo p1\n" );
- OMXInstance_SaveJavaAttributes(pOMXAV, issueCallback);
pOMXAV->width = oPortDef.format.video.nFrameWidth;
pOMXAV->height = oPortDef.format.video.nFrameHeight;
/* pOMXAV->stride = oPortDef.format.video.nStride;
pOMXAV->sliceHeight = oPortDef.format.video.nSliceHeight; */
- pOMXAV->framerate = oPortDef.format.video.xFramerate;
+ pOMXAV->framerate = (float) oPortDef.format.video.xFramerate;
pOMXAV->bitrate = oPortDef.format.video.nBitrate;
- DBG_PRINT( "Update StreamInfo p2 %dx%d, fps %d, bps %d\n", pOMXAV->width, pOMXAV->height, pOMXAV->framerate, pOMXAV->bitrate );
+ DBG_PRINT( "Update StreamInfo p2 %dx%d, fps %f, bps %d\n", pOMXAV->width, pOMXAV->height, pOMXAV->framerate, pOMXAV->bitrate );
pOMXAV->length = GetMediaLength(pOMXAV);
pOMXAV->speed = GetClockScale(pOMXAV);
- OMXInstance_UpdateJavaAttributes(pOMXAV, issueCallback);
+ if(issueCallback) {
+ OMXInstance_UpdateJavaAttributes(pOMXAV);
+ }
return err;
}
@@ -755,7 +736,7 @@ static int AttachAudioRenderer(OMXToolBasicAV_t * pOMXAV)
// FIXME: proper audio buffering ..
OMXSAFE(OMX_GetHandle(&pOMXAV->comp[OMXAV_H_ABUFFERING], "OMX.Nvidia.audio.visualization", pOMXAV, &pOMXAV->callbacks));
if(0!=(res=SyncOnState(pOMXAV->comp[OMXAV_H_ABUFFERING], OMX_StateLoaded))) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "Loading AudioBuffering Failed (%d)", res);
+ JoglCommon_throwNewRuntimeException(0, "Loading AudioBuffering Failed (%d)", res);
return res;
}
/**
@@ -777,7 +758,7 @@ static int AttachAudioRenderer(OMXToolBasicAV_t * pOMXAV)
// mandatory before SetupTunnel
if(0!=(res=SyncOnState(pOMXAV->comp[OMXAV_H_ARENDERER], OMX_StateLoaded))) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "Loading AudioRenderer Failed (%d)", res);
+ JoglCommon_throwNewRuntimeException(0, "Loading AudioRenderer Failed (%d)", res);
return res;
}
@@ -828,7 +809,7 @@ static int AttachVideoRenderer(OMXToolBasicAV_t * pOMXAV)
{
int i, res=0;
if(KD_NULL!=pOMXAV->comp[OMXAV_H_VSCHEDULER]) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "Detach Video first");
+ JoglCommon_throwNewRuntimeException(0, "Detach Video first");
return -1;
}
OMXSAFE(OMX_GetHandle(&pOMXAV->comp[OMXAV_H_VSCHEDULER], "OMX.Nvidia.video.scheduler", pOMXAV, &pOMXAV->callbacks));
@@ -836,7 +817,7 @@ static int AttachVideoRenderer(OMXToolBasicAV_t * pOMXAV)
// mandatory before SetupTunnel
if(0!=(res=SyncOnState(pOMXAV->comp[OMXAV_H_VSCHEDULER], OMX_StateLoaded))) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "Loading VideoScheduler Failed (%d)", res);
+ JoglCommon_throwNewRuntimeException(0, "Loading VideoScheduler Failed (%d)", res);
return res;
}
// mandatory before EGLUseImage
@@ -861,7 +842,7 @@ static int AttachVideoRenderer(OMXToolBasicAV_t * pOMXAV)
DBG_PRINT( "UseEGLImg %p #%d t:%d i:%p s:%p p1\n", pOMXAV, i, pBuf->tex, pBuf->image, pBuf->sync);
if(NULL==pBuf->image) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "AttachVideoRenderer: User didn't set buffer %d/%d\n", i, pOMXAV->vBufferNum);
+ JoglCommon_throwNewRuntimeException(0, "AttachVideoRenderer: User didn't set buffer %d/%d\n", i, pOMXAV->vBufferNum);
return -1;
} else {
// tell decoder output port that it will be using EGLImage
@@ -886,7 +867,7 @@ static int DetachVideoRenderer(OMXToolBasicAV_t * pOMXAV)
if(NULL==pOMXAV) return -1;
if(KD_NULL==pOMXAV->comp[OMXAV_H_VSCHEDULER]) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "Attach Video first");
+ JoglCommon_throwNewRuntimeException(0, "Attach Video first");
return -1;
}
DBG_PRINT( "DetachVideoRenderer p0\n");
@@ -968,11 +949,11 @@ void OMXToolBasicAV_SetStream(OMXToolBasicAV_t * pOMXAV, int vBufferNum, const K
// FIXME: verify player state .. ie stop !
if(pOMXAV->status!=OMXAV_INIT) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "Player instance in use\n");
+ JoglCommon_throwNewRuntimeException(0, "Player instance in use\n");
return;
}
if(vBufferNum>EGLIMAGE_MAX_BUFFERS) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "buffer number %d > MAX(%d)\n", vBufferNum, EGLIMAGE_MAX_BUFFERS);
+ JoglCommon_throwNewRuntimeException(0, "buffer number %d > MAX(%d)\n", vBufferNum, EGLIMAGE_MAX_BUFFERS);
return;
}
@@ -987,7 +968,7 @@ void OMXToolBasicAV_SetStream(OMXToolBasicAV_t * pOMXAV, int vBufferNum, const K
eError = AddFile(pOMXAV, stream);
if(eError!=OMX_ErrorNone) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "Couldn't open or handle stream: %s\n", stream);
+ JoglCommon_throwNewRuntimeException(0, "Couldn't open or handle stream: %s\n", stream);
kdThreadMutexUnlock(pOMXAV->mutex);
return;
}
@@ -1040,7 +1021,7 @@ void OMXToolBasicAV_SetStream(OMXToolBasicAV_t * pOMXAV, int vBufferNum, const K
if (pOMXAV->audioPort == -1 && pOMXAV->videoPort == -1)
{
- java_throwNewRuntimeException(pOMXAV->jni_env, "Neither audioport or videoport could be played back!\n");
+ JoglCommon_throwNewRuntimeException(0, "Neither audioport or videoport could be played back!\n");
kdThreadMutexUnlock(pOMXAV->mutex);
return;
}
@@ -1071,12 +1052,12 @@ void OMXToolBasicAV_SetStream(OMXToolBasicAV_t * pOMXAV, int vBufferNum, const K
void OMXToolBasicAV_SetStreamEGLImageTexture2D(OMXToolBasicAV_t * pOMXAV, KDint i, GLuint tex, EGLImageKHR image, EGLSyncKHR sync)
{
if(NULL==pOMXAV) {
- java_throwNewRuntimeException(0, "OMX instance null\n");
+ JoglCommon_throwNewRuntimeException(0, "OMX instance null\n");
return;
}
DBG_PRINT( "SetStreamEGLImg %p #%d/%d t:%d i:%p s:%p..\n", pOMXAV, i, pOMXAV->vBufferNum, tex, image, sync);
if(i<0||i>=pOMXAV->vBufferNum) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "Buffer index out of range: %d\n", i);
+ JoglCommon_throwNewRuntimeException(0, "Buffer index out of range: %d\n", i);
return;
}
@@ -1094,7 +1075,7 @@ void OMXToolBasicAV_SetStreamEGLImageTexture2D(OMXToolBasicAV_t * pOMXAV, KDint
void OMXToolBasicAV_ActivateStream(OMXToolBasicAV_t * pOMXAV) {
int res;
if(NULL==pOMXAV) {
- java_throwNewRuntimeException(0, "OMX instance null\n");
+ JoglCommon_throwNewRuntimeException(0, "OMX instance null\n");
return;
}
DBG_PRINT( "ActivateStream 1\n");
@@ -1115,7 +1096,7 @@ void OMXToolBasicAV_ActivateStream(OMXToolBasicAV_t * pOMXAV) {
// mandatory: before SetupTunnel (->Activate), wait until all devices are ready ..
// arender/vrender must wait as well ..
if(0!=(res=OMXToolBasicAV_WaitForState(pOMXAV, OMX_StateLoaded))) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "Loaded Failed (%d)", res);
+ JoglCommon_throwNewRuntimeException(0, "Loaded Failed (%d)", res);
kdThreadMutexUnlock(pOMXAV->mutex);
return;
}
@@ -1161,7 +1142,7 @@ void OMXToolBasicAV_ActivateStream(OMXToolBasicAV_t * pOMXAV) {
//
if(0!=(res=OMXToolBasicAV_RequestState(pOMXAV, OMX_StateIdle, KD_TRUE)))
{
- java_throwNewRuntimeException(pOMXAV->jni_env, "Wait for Idle Failed (%d)", res);
+ JoglCommon_throwNewRuntimeException(0, "Wait for Idle Failed (%d)", res);
kdThreadMutexUnlock(pOMXAV->mutex);
return;
}
@@ -1172,11 +1153,11 @@ void OMXToolBasicAV_ActivateStream(OMXToolBasicAV_t * pOMXAV) {
void OMXToolBasicAV_DetachVideoRenderer(OMXToolBasicAV_t * pOMXAV) {
if(NULL==pOMXAV) {
- java_throwNewRuntimeException(0, "OMX instance null\n");
+ JoglCommon_throwNewRuntimeException(0, "OMX instance null\n");
return;
}
if(pOMXAV->status<=OMXAV_INIT) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "OMX invalid status: %d <= INIT\n", pOMXAV->status);
+ JoglCommon_throwNewRuntimeException(0, "OMX invalid status: %d <= INIT\n", pOMXAV->status);
return;
}
kdThreadMutexLock(pOMXAV->mutex);
@@ -1188,11 +1169,11 @@ void OMXToolBasicAV_DetachVideoRenderer(OMXToolBasicAV_t * pOMXAV) {
void OMXToolBasicAV_AttachVideoRenderer(OMXToolBasicAV_t * pOMXAV) {
if(NULL==pOMXAV) {
- java_throwNewRuntimeException(0, "OMX instance null\n");
+ JoglCommon_throwNewRuntimeException(0, "OMX instance null\n");
return;
}
if(pOMXAV->status<=OMXAV_INIT) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "OMX invalid status: %d <= INIT\n", pOMXAV->status);
+ JoglCommon_throwNewRuntimeException(0, "OMX invalid status: %d <= INIT\n", pOMXAV->status);
return;
}
kdThreadMutexLock(pOMXAV->mutex);
@@ -1205,11 +1186,11 @@ void OMXToolBasicAV_AttachVideoRenderer(OMXToolBasicAV_t * pOMXAV) {
void OMXToolBasicAV_SetPlaySpeed(OMXToolBasicAV_t * pOMXAV, KDfloat32 scale)
{
if(NULL==pOMXAV) {
- java_throwNewRuntimeException(0, "OMX instance null\n");
+ JoglCommon_throwNewRuntimeException(0, "OMX instance null\n");
return;
}
if(pOMXAV->status<=OMXAV_INIT) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "OMX invalid status: %d <= INIT\n", pOMXAV->status);
+ JoglCommon_throwNewRuntimeException(0, "OMX invalid status: %d <= INIT\n", pOMXAV->status);
return;
}
kdThreadMutexLock(pOMXAV->mutex);
@@ -1226,11 +1207,11 @@ void OMXToolBasicAV_PlayStart(OMXToolBasicAV_t * pOMXAV)
{
int res;
if(NULL==pOMXAV) {
- java_throwNewRuntimeException(0, "OMX instance null\n");
+ JoglCommon_throwNewRuntimeException(0, "OMX instance null\n");
return;
}
if(pOMXAV->status<=OMXAV_INIT) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "OMX invalid status: %d <= INIT\n", pOMXAV->status);
+ JoglCommon_throwNewRuntimeException(0, "OMX invalid status: %d <= INIT\n", pOMXAV->status);
return;
}
if(pOMXAV->status==OMXAV_PLAYING) {
@@ -1244,14 +1225,14 @@ void OMXToolBasicAV_PlayStart(OMXToolBasicAV_t * pOMXAV)
DBG_PRINT( "Play 3.1\n");
if(0!=(res=OMXToolBasicAV_RequestState(pOMXAV, OMX_StateExecuting, KD_TRUE))) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "Play Execute Failed (%d)", res);
+ JoglCommon_throwNewRuntimeException(0, "Play Execute Failed (%d)", res);
kdThreadMutexUnlock(pOMXAV->mutex);
return;
}
if(pOMXAV->status==OMXAV_STOPPED || pOMXAV->status==OMXAV_FIN) {
DBG_PRINT( "Play 3.2\n");
if(StartClock(pOMXAV, KD_TRUE, 0.0)) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "Play StartClock Failed");
+ JoglCommon_throwNewRuntimeException(0, "Play StartClock Failed");
kdThreadMutexUnlock(pOMXAV->mutex);
return;
}
@@ -1275,13 +1256,13 @@ static int PlayStop(OMXToolBasicAV_t * pOMXAV)
if(OMXToolBasicAV_CheckState(pOMXAV, OMX_StateLoaded)) {
if(StartClock(pOMXAV, KD_FALSE, 0.0)) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "Stop StopClock Failed");
+ JoglCommon_throwNewRuntimeException(0, "Stop StopClock Failed");
kdThreadMutexUnlock(pOMXAV->mutex);
return -1;
}
if(OMXToolBasicAV_CheckState(pOMXAV, OMX_StateIdle)) {
if(0!=(res=OMXToolBasicAV_RequestState(pOMXAV, OMX_StateIdle, KD_TRUE))) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "Stop Idle Failed (%d)", res);
+ JoglCommon_throwNewRuntimeException(0, "Stop Idle Failed (%d)", res);
kdThreadMutexUnlock(pOMXAV->mutex);
return res;
}
@@ -1294,11 +1275,11 @@ static int PlayStop(OMXToolBasicAV_t * pOMXAV)
void OMXToolBasicAV_PlayStop(OMXToolBasicAV_t * pOMXAV)
{
if(NULL==pOMXAV) {
- java_throwNewRuntimeException(0, "OMX instance null\n");
+ JoglCommon_throwNewRuntimeException(0, "OMX instance null\n");
return;
}
if(pOMXAV->status<=OMXAV_INIT) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "OMX invalid status: %d <= INIT\n", pOMXAV->status);
+ JoglCommon_throwNewRuntimeException(0, "OMX invalid status: %d <= INIT\n", pOMXAV->status);
return;
}
kdThreadMutexLock(pOMXAV->mutex);
@@ -1312,11 +1293,11 @@ void OMXToolBasicAV_PlayPause(OMXToolBasicAV_t * pOMXAV)
{
int res;
if(NULL==pOMXAV) {
- java_throwNewRuntimeException(0, "OMX instance null\n");
+ JoglCommon_throwNewRuntimeException(0, "OMX instance null\n");
return;
}
if(pOMXAV->status<=OMXAV_INIT) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "OMX invalid status: %d <= INIT\n", pOMXAV->status);
+ JoglCommon_throwNewRuntimeException(0, "OMX invalid status: %d <= INIT\n", pOMXAV->status);
return;
}
if(pOMXAV->status==OMXAV_PAUSED || pOMXAV->status!=OMXAV_PLAYING) {
@@ -1339,11 +1320,11 @@ void OMXToolBasicAV_PlaySeek(OMXToolBasicAV_t * pOMXAV, KDint64 time)
int res;
if(NULL==pOMXAV) {
- java_throwNewRuntimeException(0, "OMX instance null\n");
+ JoglCommon_throwNewRuntimeException(0, "OMX instance null\n");
return;
}
if(pOMXAV->status<=OMXAV_INIT) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "OMX invalid status: %d <= INIT\n", pOMXAV->status);
+ JoglCommon_throwNewRuntimeException(0, "OMX invalid status: %d <= INIT\n", pOMXAV->status);
return;
}
kdThreadMutexLock(pOMXAV->mutex);
@@ -1359,7 +1340,7 @@ void OMXToolBasicAV_PlaySeek(OMXToolBasicAV_t * pOMXAV, KDint64 time)
// state transition to OMX_StatePause.
if(pOMXAV->status!=OMXAV_PAUSED) {
if(0!=(res=OMXToolBasicAV_RequestState(pOMXAV, OMX_StatePause, KD_TRUE))) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "Seek Pause Failed (%d)", res);
+ JoglCommon_throwNewRuntimeException(0, "Seek Pause Failed (%d)", res);
kdThreadMutexUnlock(pOMXAV->mutex);
return;
}
@@ -1369,7 +1350,7 @@ void OMXToolBasicAV_PlaySeek(OMXToolBasicAV_t * pOMXAV, KDint64 time)
// on OMX_TIME_CONFIG_CLOCKSTATETYPE requesting a transition to
// OMX_TIME_ClockStateStopped.
if(StartClock(pOMXAV, KD_FALSE, 0.0)) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "Seek StopClock Failed");
+ JoglCommon_throwNewRuntimeException(0, "Seek StopClock Failed");
kdThreadMutexUnlock(pOMXAV->mutex);
return;
}
@@ -1377,14 +1358,14 @@ void OMXToolBasicAV_PlaySeek(OMXToolBasicAV_t * pOMXAV, KDint64 time)
// 3. Seek to the desired location through the use of OMX_SetConfig on
// OMX_IndexConfigTimePosition requesting the desired timestamp.
if(SetMediaPosition(pOMXAV, time)) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "Seek position Failed");
+ JoglCommon_throwNewRuntimeException(0, "Seek position Failed");
kdThreadMutexUnlock(pOMXAV->mutex);
return;
}
// 4. Flush all components.
if(SendCommand(pOMXAV, OMX_CommandFlush, OMX_ALL, 0)) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "Seek Flush Failed");
+ JoglCommon_throwNewRuntimeException(0, "Seek Flush Failed");
kdThreadMutexUnlock(pOMXAV->mutex);
return;
}
@@ -1394,7 +1375,7 @@ void OMXToolBasicAV_PlaySeek(OMXToolBasicAV_t * pOMXAV, KDint64 time)
// OMX_TIME_ClockStateRunning or
// OMX_TIME_ClockStateWaitingForStartTime.
if(StartClock(pOMXAV, KD_TRUE, time)) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "Seek StartClock Failed");
+ JoglCommon_throwNewRuntimeException(0, "Seek StartClock Failed");
kdThreadMutexUnlock(pOMXAV->mutex);
return;
}
@@ -1403,7 +1384,7 @@ void OMXToolBasicAV_PlaySeek(OMXToolBasicAV_t * pOMXAV, KDint64 time)
// state transition to OMX_StateExecuting.
if(pOMXAV->status==OMXAV_PLAYING) {
if(0!=(res=OMXToolBasicAV_RequestState(pOMXAV, OMX_StateExecuting, KD_TRUE))) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "Seek Execute Failed (%d)", res);
+ JoglCommon_throwNewRuntimeException(0, "Seek Execute Failed (%d)", res);
kdThreadMutexUnlock(pOMXAV->mutex);
return;
}
@@ -1478,11 +1459,11 @@ GLuint OMXToolBasicAV_GetNextTextureID(OMXToolBasicAV_t * pOMXAV, int blocking)
KDint64 OMXToolBasicAV_GetCurrentPosition(OMXToolBasicAV_t * pOMXAV) {
KDint64 res = 0L;
if(NULL==pOMXAV) {
- java_throwNewRuntimeException(0, "OMX instance null\n");
+ JoglCommon_throwNewRuntimeException(0, "OMX instance null\n");
return res;
}
if(pOMXAV->status<=OMXAV_INIT) {
- java_throwNewRuntimeException(pOMXAV->jni_env, "OMX invalid status: %d <= INIT\n", pOMXAV->status);
+ JoglCommon_throwNewRuntimeException(0, "OMX invalid status: %d <= INIT\n", pOMXAV->status);
return res;
}
kdThreadMutexLock(pOMXAV->mutex);
diff --git a/src/jogl/native/openmax/omx_tool.h b/src/jogl/native/openmax/omx_tool.h
index 1ade60e4f..414befca0 100644
--- a/src/jogl/native/openmax/omx_tool.h
+++ b/src/jogl/native/openmax/omx_tool.h
@@ -73,16 +73,16 @@ typedef struct {
OMX_HANDLETYPE endComponent;
OMX_CALLBACKTYPE callbacks;
- KDchar audioCodec[256];
- KDchar audioCodecComponent[256];
- KDchar videoCodec[256];
- KDchar videoCodecComponent[256];
+ KDchar audioCodec[64];
+ KDchar audioCodecComponent[64];
+ KDchar videoCodec[64];
+ KDchar videoCodecComponent[64];
int audioPort;
int videoPort;
KDuint32 width;
KDuint32 height;
KDuint32 bitrate; // per seconds
- KDuint32 framerate; // per seconds
+ KDfloat32 framerate; // per seconds
KDfloat32 length; // seconds
KDfloat32 speed; // current clock scale
KDfloat32 play_speed; // current play clock scale
@@ -99,17 +99,7 @@ typedef struct {
int status;
- intptr_t jni_env;
intptr_t jni_instance;
- intptr_t jni_mid_saveAttributes;
- intptr_t jni_mid_attributesUpdated;
- intptr_t jni_fid_width;
- intptr_t jni_fid_height;
- intptr_t jni_fid_fps;
- intptr_t jni_fid_bps;
- intptr_t jni_fid_totalFrames;
- intptr_t jni_fid_acodec;
- intptr_t jni_fid_vcodec;
} OMXToolBasicAV_t ;
//