aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/com
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/classes/com
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/classes/com')
-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
2 files changed, 178 insertions, 19 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