summaryrefslogtreecommitdiffstats
path: root/src/jogl/classes
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2012-04-02 08:36:38 +0200
committerSven Gothel <[email protected]>2012-04-02 08:36:38 +0200
commit5911b729b69b7fb327e441b33f22eb1ef31a03df (patch)
tree21d91c7d84bc99e6341029e9d233d37f5a1adc23 /src/jogl/classes
parentde2b129a56335262a44a05541a3ab2e35668cc6e (diff)
Initial commit for AudioVideo (com.jogamp.opengl.av) rework, introducing Android API 14 MediaPlayer impl of GLMediaPlayer.
Android API 14 MediaPlayer allows usage of OMX AL direct decode to texture via libstagefright (OMX AL usage included). Status: Untested, not working - Need to fix native OMX IL (stream detect and split) and/or GStreamer implementation.
Diffstat (limited to 'src/jogl/classes')
-rw-r--r--src/jogl/classes/com/jogamp/opengl/av/GLMediaEventListener.java17
-rw-r--r--src/jogl/classes/com/jogamp/opengl/av/GLMediaPlayer.java90
-rw-r--r--src/jogl/classes/com/jogamp/opengl/av/GLMediaPlayerFactory.java18
-rw-r--r--src/jogl/classes/com/jogamp/openmax/OMXEventListener.java14
-rw-r--r--src/jogl/classes/com/jogamp/openmax/OMXInstance.java509
-rw-r--r--src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java195
-rw-r--r--src/jogl/classes/jogamp/opengl/av/EGLMediaPlayerImpl.java109
-rw-r--r--src/jogl/classes/jogamp/opengl/av/GLMediaPlayerImpl.java307
-rw-r--r--src/jogl/classes/jogamp/opengl/omx/OMXGLMediaPlayer.java238
9 files changed, 974 insertions, 523 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/av/GLMediaEventListener.java b/src/jogl/classes/com/jogamp/opengl/av/GLMediaEventListener.java
new file mode 100644
index 000000000..a02c8a362
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/av/GLMediaEventListener.java
@@ -0,0 +1,17 @@
+
+package com.jogamp.opengl.av;
+
+import com.jogamp.opengl.av.GLMediaPlayer.TextureFrame;
+
+public interface GLMediaEventListener {
+
+ static final int EVENT_CHANGE_SIZE = 1<<0;
+ static final int EVENT_CHANGE_FPS = 1<<1;
+ static final int EVENT_CHANGE_BPS = 1<<2;
+ static final int EVENT_CHANGE_LENGTH = 1<<3;
+
+ public void attributesChanges(GLMediaPlayer mp, int event_mask);
+ public void newFrameAvailable(GLMediaPlayer mp, TextureFrame frame);
+
+}
+
diff --git a/src/jogl/classes/com/jogamp/opengl/av/GLMediaPlayer.java b/src/jogl/classes/com/jogamp/opengl/av/GLMediaPlayer.java
new file mode 100644
index 000000000..71e0e16d9
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/av/GLMediaPlayer.java
@@ -0,0 +1,90 @@
+package com.jogamp.opengl.av;
+
+import java.io.IOException;
+import java.net.URL;
+
+import javax.media.opengl.GL;
+
+import com.jogamp.opengl.util.texture.Texture;
+
+/**
+ * Lifecycle of an GLMediaPlayer:
+ * <ul>
+ * <li>{@link #setStream(GL, URL)}</li>
+ * <li>{@link #start()}</li>
+ * <li>{@link #stop()}</li>
+ * <li>{@link #destroy(GL)}</li>
+ * </ul>
+ */
+public interface GLMediaPlayer {
+
+ public static class TextureFrame {
+ public TextureFrame(Texture t) {
+ texture = t;
+ }
+
+ public final Texture getTexture() { return texture; }
+
+ public String toString() {
+ return "TextureFrame[" + texture + "]";
+ }
+ protected final Texture texture;
+ }
+
+ /** Sets the stream to be used. Initializes all stream related states and GL resources. */
+ public void setStream(GL gl, URL url) throws IOException;
+
+ /** Releases the GL and stream resources. */
+ public void destroy(GL gl);
+
+ public void setPlaySpeed(float rate);
+
+ public float getPlaySpeed();
+
+ public void start();
+
+ public void pause();
+
+ public void stop();
+
+ /**
+ * @return time current position in milliseconds
+ **/
+ public int getCurrentPosition();
+
+ /**
+ * @param msec absolute desired time position in milliseconds
+ * @return time current position in milliseconds, after seeking to the desired position
+ **/
+ public int seek(int msec);
+
+ public Texture getLastTextureID();
+
+ public Texture getNextTextureID();
+
+ public boolean isValid();
+
+ public URL getURL();
+
+ public String getVideoCodec();
+
+ public String getAudioCodec();
+
+ public long getTotalFrames();
+
+ public long getBitrate();
+
+ public int getFramerate();
+
+ public int getWidth();
+
+ public int getHeight();
+
+ public String toString();
+
+ public void addEventListener(GLMediaEventListener l);
+
+ public void removeEventListener(GLMediaEventListener l);
+
+ public GLMediaEventListener[] getEventListeners();
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/av/GLMediaPlayerFactory.java b/src/jogl/classes/com/jogamp/opengl/av/GLMediaPlayerFactory.java
new file mode 100644
index 000000000..0025a70ba
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/av/GLMediaPlayerFactory.java
@@ -0,0 +1,18 @@
+package com.jogamp.opengl.av;
+
+import com.jogamp.common.os.AndroidVersion;
+import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.ReflectionUtil;
+
+public class GLMediaPlayerFactory {
+ private static final String AndroidGLMediaPlayerAPI14ClazzName = "jogamp.opengl.android.av.AndroidGLMediaPlayerAPI14";
+
+ public static GLMediaPlayer create() {
+ if(Platform.OS_TYPE.equals(Platform.OSType.ANDROID)) {
+ if(AndroidVersion.SDK_INT >= 14) {
+ return (GLMediaPlayer) ReflectionUtil.createInstance(AndroidGLMediaPlayerAPI14ClazzName, GLMediaPlayerFactory.class.getClassLoader());
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/openmax/OMXEventListener.java b/src/jogl/classes/com/jogamp/openmax/OMXEventListener.java
deleted file mode 100644
index 08cfeccde..000000000
--- a/src/jogl/classes/com/jogamp/openmax/OMXEventListener.java
+++ /dev/null
@@ -1,14 +0,0 @@
-
-package com.jogamp.openmax;
-
-public interface OMXEventListener {
-
- static final int EVENT_CHANGE_SIZE = 1<<0;
- static final int EVENT_CHANGE_FPS = 1<<1;
- static final int EVENT_CHANGE_BPS = 1<<2;
- static final int EVENT_CHANGE_LENGTH = 1<<3;
-
- public void changedAttributes(OMXInstance omx, int event_mask);
-
-}
-
diff --git a/src/jogl/classes/com/jogamp/openmax/OMXInstance.java b/src/jogl/classes/com/jogamp/openmax/OMXInstance.java
deleted file mode 100644
index 7c373a0ef..000000000
--- a/src/jogl/classes/com/jogamp/openmax/OMXInstance.java
+++ /dev/null
@@ -1,509 +0,0 @@
-
-package com.jogamp.openmax;
-
-import javax.media.opengl.*;
-import javax.media.opengl.glu.GLU;
-import com.jogamp.opengl.util.texture.*;
-
-import jogamp.opengl.egl.EGL;
-import jogamp.opengl.egl.EGLContext;
-import jogamp.opengl.egl.EGLDrawable;
-import jogamp.opengl.egl.EGLExt;
-
-import java.net.URL;
-import java.nio.ByteBuffer;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.util.*;
-
-public class OMXInstance {
- private long moviePtr = 0;
-
- protected String path = null;
- protected URL url = null;
-
- // *** Texture impl
- protected Texture texture = null; // holds the last fetched texture
-
- protected float playSpeed = 1.0f;
-
- /**
- * The following data is set by the setStream function,
- * and may be set by the native OMX implementation,
- * in case the stream attributes changes (see attributesUpdated)
- */
- protected int width = 0;
- protected int height = 0;
- protected int fps = 0; // frames per seconds
- protected long bps = 0; // bits per seconds
- protected long totalFrames = 0; // duration in frames
- protected String acodec = null;
- protected String vcodec = null;
-
- /**
- * Old stream values, before the last attributesUpdated)
- */
- protected int o_width = 0;
- protected int o_height = 0;
- protected int o_fps = 0; // frames per seconds
- protected long o_bps = 0; // bits per seconds
- protected long o_totalFrames = 0; // duration in frames
-
- static class EGLImageTexture {
- public EGLImageTexture(com.jogamp.opengl.util.texture.Texture t, long i, long s) {
- texture = t; image = i; sync = s;
- }
- public String toString() {
- return "EGLImageTexture[" + texture + ", image " + image + ", sync "+sync+"]";
- }
- protected com.jogamp.opengl.util.texture.Texture texture;
- protected long image;
- protected long sync;
- }
- private EGLImageTexture[] eglImgTexs=null;
- private HashMap eglImgTexsMap = new HashMap();
- protected int textureNum;
-
- private EGLExt eglExt = null;
- private long eglSurface = 0;
- private long eglDisplay = 0;
- private long eglContext = 0;
- private int sWidth=0, sHeight=0;
-
- private GL initGLData(GL gl) {
- if(null==gl) {
- throw new RuntimeException("No current GL");
- }
- EGLContext eglCtx = (EGLContext) gl.getContext();
- if(null==eglCtx) {
- throw new RuntimeException("No current EGL context");
- }
- EGLDrawable eglDrawable = (EGLDrawable) eglCtx.getGLDrawable();
- if(null==eglDrawable) {
- throw new RuntimeException("No valid drawable");
- }
- eglContext = eglCtx.getHandle();
- eglDisplay = eglDrawable.getDisplay();
- eglSurface = eglDrawable.getHandle();
- eglExt = eglCtx.getEGLExt();
- if(null==eglExt) {
- throw new RuntimeException("No valid EGLExt");
- }
-
- int iTmp[] = new int[1];
- EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_WIDTH, iTmp, 0);
- sWidth=iTmp[0];
- EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_HEIGHT, iTmp, 0);
- sHeight=iTmp[0];
- System.out.println("surface size: "+width+"x"+height);
- System.out.println(eglDrawable);
- System.out.println(eglCtx);
- System.out.println("EGL Extensions : "+EGL.eglQueryString(eglDisplay, EGL.EGL_EXTENSIONS));
- System.out.println("EGL CLIENT APIs: "+EGL.eglQueryString(eglDisplay, EGL.EGL_CLIENT_APIS));
- return gl;
- }
-
- public OMXInstance() {
- moviePtr = _createInstance();
- if(0==moviePtr) {
- throw new GLException("Couldn't create OMXInstance");
- }
- }
- native long _createInstance();
-
- public synchronized void setStream(int textureNum, URL u) {
- if(0==moviePtr) {
- throw new GLException("OMX native instance null");
- }
- this.textureNum=textureNum;
- url = u;
- if (url == null) {
- System.out.println("setURL (null)");
- stop();
- return;
- }
- path=null;
- if (url.getProtocol() == null || "file".equals(url.getProtocol())) {
- // CV only accepts absolute paths
- try {
- File file = new File(url.getPath());
- if (!file.exists()) {
- throw new RuntimeException(new FileNotFoundException(file.toString()));
- }
- path = file.getCanonicalPath();
- System.out.println("setURL: path "+path);
- } catch (Exception e) {
- e.printStackTrace();
- throw new RuntimeException(e);
- }
- }
- path = replaceAll(path, "\\", "/").trim();
- if(null==path) {
- throw new RuntimeException("Couldn't parse stream URL: "+url);
- }
- System.out.println("setURL: clean path "+path);
-
- System.out.println("setURL: p1 "+this);
- _setStream(moviePtr, textureNum, path);
- System.out.println("setURL: p2 "+this);
- }
- native void _setStream(long moviePtr, int textureNum, String path);
-
- public synchronized void setStreamAllEGLImageTexture2D(GL gl) {
- if(0==moviePtr) {
- throw new GLException("OMX native instance null");
- }
- if(null==vcodec) {
- return;
- }
- gl = initGLData(gl);
-
- if(null!=eglImgTexs) {
- removeAllEGLImageTexture2D(gl);
- } else {
- eglImgTexs = new EGLImageTexture[textureNum];
- }
-
- int[] tmp = new int[1];
- int tex, e;
-
- errorCheckGL(gl, "i.1");
- gl.glEnable(gl.GL_TEXTURE_2D);
- errorCheckGL(gl, "i.2");
-
- for(int i=0; i<textureNum; i++) {
- String s0 = String.valueOf(i);
- gl.glGenTextures(1, tmp, 0);
- tex=tmp[0];
- if( (e=gl.glGetError()) != GL.GL_NO_ERROR || 0>tex ) {
- throw new RuntimeException("TextureName creation failed: "+e);
- }
- gl.glBindTexture(gl.GL_TEXTURE_2D, tex);
-
- // create space for buffer with a texture
- gl.glTexImage2D(
- gl.GL_TEXTURE_2D, // target
- 0, // level
- gl.GL_RGBA, // internal format
- width, // width
- height, // height
- 0, // border
- gl.GL_RGBA, // format
- gl.GL_UNSIGNED_BYTE, // type
- null); // pixels -- will be provided later
- gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST);
- gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST);
-
- long image=0, sync=0;
-
- // create EGLImage from texture
- tmp[0] = EGL.EGL_NONE;
- image = eglExt.eglCreateImageKHR(
- eglDisplay,
- eglContext,
- eglExt.EGL_GL_TEXTURE_2D_KHR,
- tex,
- tmp, 0);
- if (0==image) {
- throw new RuntimeException("EGLImage creation failed: "+EGL.eglGetError()+", dpy "+eglDisplay+", ctx "+eglContext+", tex "+tex);
- }
-
- // 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.
- tmp[0] = EGL.EGL_NONE;
- sync = eglExt.eglCreateSyncKHR(
- eglDisplay,
- eglExt.EGL_SYNC_FENCE_KHR, tmp, 0);
-
- _setStreamEGLImageTexture2D(moviePtr, i, tex, image, sync);
-
- eglImgTexs[i] = new EGLImageTexture(
- com.jogamp.opengl.util.texture.TextureIO.newTexture(tex,
- javax.media.opengl.GL2.GL_TEXTURE_2D,
- width,
- height,
- width,
- height,
- true),
- image, sync);
- eglImgTexsMap.put(new Integer(tex), eglImgTexs[i]);
- }
- gl.glDisable(gl.GL_TEXTURE_2D);
- }
- native void _setStreamEGLImageTexture2D(long moviePtr, int i, int tex, long image, long sync);
-
- public synchronized void activateStream() {
- if(0==moviePtr) {
- throw new GLException("OMX native instance null");
- }
- _activateStream(moviePtr);
- }
- native void _activateStream(long moviePtr);
-
- public synchronized void detachVideoRenderer() {
- if(0==moviePtr) {
- throw new GLException("OMX native instance null");
- }
- _detachVideoRenderer(moviePtr);
- }
- native void _detachVideoRenderer(long moviePtr); // stop before
-
- public synchronized void attachVideoRenderer() {
- if(0==moviePtr) {
- throw new GLException("OMX native instance null");
- }
- _attachVideoRenderer(moviePtr);
- }
- native void _attachVideoRenderer(long moviePtr); // detach before
-
- public synchronized void setPlaySpeed(float rate) {
- if(0==moviePtr) {
- throw new GLException("OMX native instance null");
- }
- _setPlaySpeed(moviePtr, rate);
- playSpeed = rate;
- }
- public synchronized float getPlaySpeed() {
- return playSpeed;
- }
- native void _setPlaySpeed(long moviePtr, float rate);
-
- /** @return time position after issuing the command */
- public synchronized float play() {
- if(0==moviePtr) {
- throw new GLException("OMX native instance null");
- }
- return _play(moviePtr);
- }
- native float _play(long moviePtr);
-
- /** @return time position after issuing the command */
- public synchronized float pause() {
- if(0==moviePtr) {
- throw new GLException("OMX native instance null");
- }
- return _pause(moviePtr);
- }
- native float _pause(long moviePtr);
-
- /** @return time position after issuing the command */
- public synchronized float stop() {
- if(0==moviePtr) {
- throw new GLException("OMX native instance null");
- }
- return _stop(moviePtr);
- }
- native float _stop(long moviePtr);
-
- /** @return time position after issuing the command */
- public synchronized float seek(float pos) {
- if(0==moviePtr) {
- throw new GLException("OMX native instance null");
- }
- return _seek(moviePtr, pos);
- }
- native float _seek(long moviePtr, float position);
-
- public synchronized Texture getLastTextureID() {
- return texture;
- }
- public synchronized Texture getNextTextureID() {
- if(0==moviePtr) {
- throw new GLException("OMX native instance null");
- }
- texture=null;
- EGLImageTexture eglImgTex = (EGLImageTexture) eglImgTexsMap.get(new Integer(_getNextTextureID(moviePtr)));
- if(null!=eglImgTex) {
- texture = eglImgTex.texture;
- }
- return texture;
- }
- native int _getNextTextureID(long moviePtr);
-
- public synchronized float getCurrentPosition() {
- if(0==moviePtr) {
- throw new GLException("OMX native instance null");
- }
- return _getCurrentPosition(moviePtr);
- }
- native float _getCurrentPosition(long moviePtr);
-
- public synchronized void destroy(GL gl) {
- removeAllEGLImageTexture2D(gl);
- if (moviePtr != 0) {
- long ptr = moviePtr;
- moviePtr = 0;
- _destroyInstance(ptr);
-
- eglExt=null;
- eglSurface=0;
- eglDisplay=0;
- eglContext=0;
- }
- }
- protected synchronized void finalize() {
- if (moviePtr != 0) {
- destroy(null);
- }
- }
- native void _destroyInstance(long moviePtr);
-
- public synchronized boolean isValid() {
- return (moviePtr != 0);
- }
- public synchronized String getPath() {
- return path;
- }
- public synchronized URL getURL() {
- return url;
- }
- public synchronized String getVideoCodec() {
- return vcodec;
- }
- public synchronized String getAudioCodec() {
- return acodec;
- }
- public synchronized long getTotalFrames() {
- return totalFrames;
- }
- public synchronized long getBitrate() {
- return bps;
- }
- public synchronized int getFramerate() {
- return fps;
- }
- public synchronized int getWidth() {
- return width;
- }
- public synchronized int getHeight() {
- return height;
- }
- public synchronized String toString() {
- return "OMXInstance [ stream [ video [ "+vcodec+", "+width+"x"+height+", "+fps+"fps, "+bps+"bsp, "+totalFrames+"f ] ] ]";
- }
-
- /**
- * 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;
- }
-
- private void attributesUpdated() {
- int event_mask = 0;
- if( o_width != width || o_height != height ) {
- event_mask |= OMXEventListener.EVENT_CHANGE_SIZE;
- }
- if( o_fps != fps ) {
- event_mask |= OMXEventListener.EVENT_CHANGE_FPS;
- }
- if( o_bps != bps ) {
- event_mask |= OMXEventListener.EVENT_CHANGE_BPS;
- }
- if( o_totalFrames != totalFrames ) {
- event_mask |= OMXEventListener.EVENT_CHANGE_LENGTH;
- }
- if(0==event_mask) {
- return;
- }
-
- ArrayList listeners = null;
- synchronized(this) {
- listeners = eventListeners;
- }
- for(Iterator i = listeners.iterator(); i.hasNext(); ) {
- OMXEventListener l = (OMXEventListener) i.next();
- l.changedAttributes(this, event_mask);
- }
- }
-
- private String replaceAll(String orig, String search, String repl) {
- String dest=null;
- // In case replaceAll / java.util.regex.* is not supported (-> CVM)
- int i=0,j;
- dest = new String();
- while((j=orig.indexOf(search, i))>=0) {
- dest=dest.concat(orig.substring(i, j));
- dest=dest.concat(repl);
- i=j+1;
- }
- return dest.concat(orig.substring(i, orig.length()));
- }
-
- private void removeAllEGLImageTexture2D(GL gl) {
- if (moviePtr != 0) {
- if(null==eglExt) {
- throw new RuntimeException("No valid EGLExt");
- }
-
- texture = null;
- for(int i=0; i<textureNum; i++) {
- if(null!=eglImgTexs[i]) {
- if(0!=eglImgTexs[i].image) {
- eglExt.eglDestroyImageKHR(
- eglDisplay,
- eglImgTexs[i].image);
- }
- if(0!=eglImgTexs[i].sync) {
- eglExt.eglDestroySyncKHR(eglDisplay, eglImgTexs[i].sync);
- }
- if(null!=gl) {
- eglImgTexs[i].texture.destroy(gl);
- }
- eglImgTexs[i]=null;
- }
- }
- eglImgTexsMap.clear();
- }
- }
-
- private void errorCheckGL(GL gl, String s) {
- int e;
- if( (e=gl.glGetError()) != GL.GL_NO_ERROR ) {
- System.out.println("GL Error: ("+s+"): "+e);
- }
- }
-
- private void errorCheckEGL(String s) {
- int e;
- if( (e=EGL.eglGetError()) != EGL.EGL_SUCCESS ) {
- System.out.println("EGL Error: ("+s+"): 0x"+Integer.toHexString(e));
- }
- }
-
-
- //
- // OMXEventListener Support
- //
-
- public synchronized void addEventListener(OMXEventListener l) {
- if(l == null) {
- return;
- }
- ArrayList newEventListeners = (ArrayList) eventListeners.clone();
- newEventListeners.add(l);
- eventListeners = newEventListeners;
- }
-
- public synchronized void removeEventListener(OMXEventListener l) {
- if (l == null) {
- return;
- }
- ArrayList newEventListeners = (ArrayList) eventListeners.clone();
- newEventListeners.remove(l);
- eventListeners = newEventListeners;
- }
-
- public synchronized OMXEventListener[] getEventListeners() {
- return (OMXEventListener[]) eventListeners.toArray();
- }
-
- private ArrayList eventListeners = new ArrayList();
-
-}
-
diff --git a/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java b/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java
new file mode 100644
index 000000000..adfe2a048
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java
@@ -0,0 +1,195 @@
+package jogamp.opengl.android.av;
+
+import java.io.IOException;
+import java.net.URL;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLES2;
+
+import jogamp.common.os.android.StaticContext;
+import jogamp.opengl.av.GLMediaPlayerImpl;
+
+import android.graphics.SurfaceTexture;
+import android.graphics.SurfaceTexture.OnFrameAvailableListener;
+import android.media.MediaPlayer;
+import android.net.Uri;
+import android.view.Surface;
+
+import com.jogamp.opengl.av.GLMediaEventListener;
+import com.jogamp.opengl.av.GLMediaPlayer;
+import com.jogamp.opengl.av.GLMediaPlayer.TextureFrame;
+import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.opengl.util.texture.Texture;
+import com.jogamp.opengl.util.texture.TextureCoords;
+
+/***
+ * Android API Level 14: {@link MediaPlayer#setSurface(Surface)}
+ * Android API Level 14: {@link Surface#Surface(android.graphics.SurfaceTexture)}
+ */
+public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl {
+ MediaPlayer mp;
+ boolean updateSurface = false;
+
+ public static class AndroidTextureFrame extends TextureFrame {
+ public AndroidTextureFrame(Texture t, SurfaceTexture stex) {
+ super(t);
+ this.stex = stex;
+ }
+
+ public final SurfaceTexture getSurfaceTexture() { return stex; }
+
+ public String toString() {
+ return "AndroidTextureFrame[" + texture + ", "+ stex + "]";
+ }
+ protected SurfaceTexture stex;
+ }
+
+ public AndroidGLMediaPlayerAPI14() {
+ super();
+ this.setTextureTarget(GLES2.GL_TEXTURE_EXTERNAL_OES);
+ this.setTextureCount(1);
+ mp = new MediaPlayer();
+ }
+
+ @Override
+ public void setPlaySpeed(float rate) {
+ // n/a
+ }
+
+ @Override
+ public void start() {
+ mp.start();
+ }
+
+ @Override
+ public void pause() {
+ mp.pause();
+ }
+
+ @Override
+ public void stop() {
+ mp.stop();
+ }
+
+ @Override
+ public int seek(int msec) {
+ mp.seekTo(msec);
+ return mp.getCurrentPosition();
+ }
+
+ @Override
+ public Texture getNextTextureID() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public int getCurrentPosition() {
+ return mp.getCurrentPosition();
+ }
+
+ @Override
+ public boolean isValid() {
+ return true;
+ }
+
+ AndroidTextureFrame androidTextureFrame = null;
+
+ @Override
+ protected void destroyImpl(GL gl) {
+ mp.release();
+ mp = null;
+ }
+
+ @Override
+ protected void setStreamImpl() throws IOException {
+ try {
+ final Uri uri = Uri.parse(url.toExternalForm());
+ mp.setDataSource(StaticContext.getContext(), uri);
+ } catch (IllegalArgumentException e) {
+ throw new RuntimeException(e);
+ } catch (SecurityException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalStateException e) {
+ throw new RuntimeException(e);
+ }
+ mp.prepare();
+
+ width = mp.getVideoWidth();
+ height = mp.getVideoHeight();
+ fps = 0;
+ bps = 0;
+ totalFrames = mp.getDuration();
+ acodec = "unknown";
+ vcodec = "unknown";
+ }
+
+ @Override
+ protected void destroyTexImage(GLContext ctx, TextureFrame imgTex) {
+ final AndroidTextureFrame atf = (AndroidTextureFrame) imgTex;
+ atf.getSurfaceTexture().release();
+ super.destroyTexImage(ctx, imgTex);
+ }
+
+ @Override
+ protected AndroidTextureFrame createTexImage(GLContext ctx, int idx, int[] tex) {
+ final GL gl = ctx.getGL();
+
+ if( 0 > tex[idx] ) {
+ throw new RuntimeException("TextureName "+toHexString(tex[idx])+" invalid.");
+ }
+ gl.glBindTexture(GLES2.GL_TEXTURE_EXTERNAL_OES, tex[idx]);
+ {
+ final int err = gl.glGetError();
+ if( GL.GL_NO_ERROR != err ) {
+ throw new RuntimeException("Couldn't bind textureName "+toHexString(tex[idx])+" to 2D target, err "+toHexString(err));
+ }
+ }
+ // gl.glTexParameterf(GLES2.GL_TEXTURE_EXTERNAL_OES, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
+ // gl.glTexParameterf(GLES2.GL_TEXTURE_EXTERNAL_OES, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
+ gl.glTexParameterf(GLES2.GL_TEXTURE_EXTERNAL_OES, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
+ gl.glTexParameterf(GLES2.GL_TEXTURE_EXTERNAL_OES, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
+ // Clamp to edge is only option.
+ gl.glTexParameteri(GLES2.GL_TEXTURE_EXTERNAL_OES, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE);
+ gl.glTexParameteri(GLES2.GL_TEXTURE_EXTERNAL_OES, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE);
+
+ SurfaceTexture stex = new SurfaceTexture(tex[idx]);
+ stex.setOnFrameAvailableListener(onFrameAvailableListener);
+
+ return new AndroidTextureFrame( com.jogamp.opengl.util.texture.TextureIO.newTexture(tex[idx],
+ GLES2.GL_TEXTURE_EXTERNAL_OES,
+ width, height,
+ width, height,
+ true), stex);
+ }
+
+ protected OnFrameAvailableListener onFrameAvailableListener = new OnFrameAvailableListener() {
+ @Override
+ public void onFrameAvailable(SurfaceTexture surfaceTexture) {
+ frameNumber++;
+ updateSurface = true;
+ }
+ };
+
+ @Override
+ public float getPlaySpeed() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ private float[] mSTMatrix = new float[16];
+
+ @Override
+ public Texture getLastTextureID() {
+ if(updateSurface) {
+ androidTextureFrame.getSurfaceTexture().updateTexImage();
+ androidTextureFrame.getSurfaceTexture().getTransformMatrix(mSTMatrix);
+ TextureCoords tc = androidTextureFrame.getTexture().getImageTexCoords();
+ PMVMatrix pmv;
+ }
+ return androidTextureFrame.getTexture();
+ }
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/av/EGLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/av/EGLMediaPlayerImpl.java
new file mode 100644
index 000000000..ef3d5072c
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/av/EGLMediaPlayerImpl.java
@@ -0,0 +1,109 @@
+package jogamp.opengl.av;
+
+import javax.media.opengl.GLContext;
+
+import com.jogamp.opengl.util.texture.Texture;
+
+import jogamp.opengl.egl.EGL;
+import jogamp.opengl.egl.EGLContext;
+import jogamp.opengl.egl.EGLDrawable;
+import jogamp.opengl.egl.EGLExt;
+
+public abstract class EGLMediaPlayerImpl extends GLMediaPlayerImpl {
+ TextureType texType;
+ boolean useKHRSync;
+
+ public enum TextureType {
+ GL(0), KHRImage(1);
+
+ public final int id;
+
+ TextureType(int id){
+ this.id = id;
+ }
+ }
+
+ public static class EGLTextureFrame extends TextureFrame {
+
+ public EGLTextureFrame(Texture t, long khrImage, long khrSync) {
+ super(t);
+ this.image = khrImage;
+ this.sync = khrSync;
+ }
+
+ public final long getImage() { return image; }
+ public final long getSync() { return sync; }
+
+ public String toString() {
+ return "EGLTextureFrame[" + texture + ", img "+ image + ", sync "+ sync+"]";
+ }
+ protected final long image;
+ protected final long sync;
+ }
+
+
+ protected EGLMediaPlayerImpl() {
+ this(TextureType.GL, false);
+ }
+
+ protected EGLMediaPlayerImpl(TextureType texType, boolean useKHRSync) {
+ super();
+ this.texType = texType;
+ this.useKHRSync = useKHRSync;
+ }
+
+ @Override
+ protected TextureFrame createTexImage(GLContext ctx, int idx, int[] tex) {
+ final Texture texture = super.createTexImageImpl(ctx, idx, tex, true);
+ final long image;
+ final long sync;
+
+ final EGLContext eglCtx = (EGLContext) ctx;
+ final EGLExt eglExt = eglCtx.getEGLExt();
+ final EGLDrawable eglDrawable = (EGLDrawable) eglCtx.getGLDrawable();
+ int[] tmp = new int[1];
+
+ if(TextureType.KHRImage == texType) {
+ // create EGLImage from texture
+ tmp[0] = EGL.EGL_NONE;
+ image = eglExt.eglCreateImageKHR( eglDrawable.getDisplay(), eglCtx.getHandle(),
+ EGLExt.EGL_GL_TEXTURE_2D_KHR,
+ tex[idx], tmp, 0);
+ if (0==image) {
+ throw new RuntimeException("EGLImage creation failed: "+EGL.eglGetError()+", ctx "+eglCtx+", tex "+tex[idx]+", err "+toHexString(EGL.eglGetError()));
+ }
+ } else {
+ image = 0;
+ }
+
+ if(useKHRSync) {
+ // 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.
+ tmp[0] = EGL.EGL_NONE;
+ sync = eglExt.eglCreateSyncKHR(eglDrawable.getDisplay(), EGLExt.EGL_SYNC_FENCE_KHR, tmp, 0);
+ if (0==sync) {
+ throw new RuntimeException("EGLSync creation failed: "+EGL.eglGetError()+", ctx "+eglCtx+", err "+toHexString(EGL.eglGetError()));
+ }
+ } else {
+ sync = 0;
+ }
+ return new EGLTextureFrame(texture, image, sync);
+ }
+
+ @Override
+ protected void destroyTexImage(GLContext ctx, TextureFrame imgTex) {
+ final EGLContext eglCtx = (EGLContext) ctx;
+ final EGLExt eglExt = eglCtx.getEGLExt();
+ final EGLDrawable eglDrawable = (EGLDrawable) eglCtx.getGLDrawable();
+ final EGLTextureFrame eglTex = (EGLTextureFrame) imgTex;
+
+ if(0!=eglTex.getImage()) {
+ eglExt.eglDestroyImageKHR(eglDrawable.getDisplay(), eglTex.getImage());
+ }
+ if(0!=eglTex.getSync()) {
+ eglExt.eglDestroySyncKHR(eglDrawable.getDisplay(), eglTex.getSync());
+ }
+ super.destroyTexImage(ctx, imgTex);
+ }
+}
diff --git a/src/jogl/classes/jogamp/opengl/av/GLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/av/GLMediaPlayerImpl.java
new file mode 100644
index 000000000..826bb6953
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/av/GLMediaPlayerImpl.java
@@ -0,0 +1,307 @@
+package jogamp.opengl.av;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLES2;
+
+import com.jogamp.opengl.av.GLMediaPlayer;
+import com.jogamp.opengl.av.GLMediaEventListener;
+import com.jogamp.opengl.util.texture.Texture;
+
+/**
+ * After object creation an implementation may customize the behavior:
+ * <ul>
+ * <li>{@link #setTextureCount(int)}</li>
+ * <li>{@link #setTextureTarget(int)}</li>
+ * <li>{@link EGLMediaPlayerImpl#setEGLTexImageAttribs(boolean, boolean)}.</li>
+ * </ul>
+ *
+ * <p>
+ * See {@link GLMediaPlayer}.
+ * </p>
+ */
+public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
+
+ protected int textureCount;
+ protected int textureTarget;
+
+ private int sWidth = 0;
+ private int sHeight = 0;
+ protected URL url = null;
+
+ protected Texture texture = null;
+ protected float playSpeed = 1.0f;
+
+ /** Shall be set by the {@link #setStreamImpl()} method implementation. */
+ protected int width = 0;
+ /** Shall be set by the {@link #setStreamImpl()} method implementation. */
+ protected int height = 0;
+ /** Shall be set by the {@link #setStreamImpl()} method implementation. */
+ protected int fps = 0;
+ /** Shall be set by the {@link #setStreamImpl()} method implementation. */
+ protected long bps = 0;
+ /** Shall be set by the {@link #setStreamImpl()} method implementation. */
+ protected long totalFrames = 0;
+ /** Shall be set by the {@link #setStreamImpl()} method implementation. */
+ protected String acodec = null;
+ /** Shall be set by the {@link #setStreamImpl()} method implementation. */
+ protected String vcodec = null;
+
+ protected long frameNumber = 0;
+
+ private TextureFrame[] texFrames = null;
+ protected HashMap<Integer, TextureFrame> texFrameMap = new HashMap<Integer, TextureFrame>();
+ private ArrayList<GLMediaEventListener> eventListeners = new ArrayList<GLMediaEventListener>();
+
+ protected GLMediaPlayerImpl() {
+ this.textureCount=3;
+ this.textureTarget=GL.GL_TEXTURE_2D;
+ }
+
+ protected final void setTextureCount(int textureCount) {
+ this.textureCount=textureCount;
+ }
+ protected final void setTextureTarget(int textureTarget) {
+ this.textureTarget=textureTarget;
+ }
+
+ @Override
+ public final void setStream(GL gl, URL url) throws IOException {
+ this.url = url;
+ if (this.url == null) {
+ System.out.println("setURL (null)");
+ stop();
+ return;
+ }
+ setStreamImpl();
+ init(gl);
+ }
+
+ /**
+ * Implementation shall set the following set of data:
+ * @see #width
+ * @see #height
+ * @see #fps
+ * @see #bps
+ * @see #totalFrames
+ * @see #acodec
+ * @see #vcodec
+ */
+ protected abstract void setStreamImpl() throws IOException;
+
+ protected final void init(GL gl) {
+ final GLContext ctx = gl.getContext();
+ if(!ctx.isCurrent()) {
+ throw new RuntimeException("Not current: "+ctx);
+ }
+
+ final GLDrawable drawable = ctx.getGLDrawable();
+ sWidth = drawable.getWidth();
+ sHeight = drawable.getHeight();
+ System.out.println("surface size: "+sWidth+"x"+sHeight);
+ System.out.println("Platform Extensions : "+ctx.getPlatformExtensionsString());
+
+ if(null!=texFrames) {
+ removeAllImageTextures(ctx);
+ } else {
+ texFrames = new TextureFrame[textureCount];
+ }
+
+ final int[] tex = new int[textureCount];
+ {
+ gl.glGenTextures(textureCount, tex, 0);
+ final int err = gl.glGetError();
+ if( GL.GL_NO_ERROR != err ) {
+ throw new RuntimeException("TextureNames creation failed (num: "+textureCount+"): err "+toHexString(err));
+ }
+ }
+
+ for(int i=0; i<textureCount; i++) {
+ final TextureFrame tf = createTexImage(ctx, i, tex);
+ texFrames[i] = tf;
+ texFrameMap.put(tex[i], tf);
+ }
+ }
+
+ protected TextureFrame createTexImage(GLContext ctx, int idx, int[] tex) {
+ return new TextureFrame( createTexImageImpl(ctx, idx, tex, true) );
+ }
+
+ protected Texture createTexImageImpl(GLContext ctx, int idx, int[] tex, boolean mustFlipVertically) {
+ final GL gl = ctx.getGL();
+ if( 0 > tex[idx] ) {
+ throw new RuntimeException("TextureName "+toHexString(tex[idx])+" invalid.");
+ }
+ gl.glBindTexture(textureTarget, tex[idx]);
+ {
+ final int err = gl.glGetError();
+ if( GL.GL_NO_ERROR != err ) {
+ throw new RuntimeException("Couldn't bind textureName "+toHexString(tex[idx])+" to 2D target, err "+toHexString(err));
+ }
+ }
+
+ // create space for buffer with a texture
+ gl.glTexImage2D(
+ textureTarget, // target
+ 0, // level
+ GL.GL_RGBA, // internal format
+ width, // width
+ height, // height
+ 0, // border
+ GL.GL_RGBA, // format
+ GL.GL_UNSIGNED_BYTE, // type
+ null); // pixels -- will be provided later
+ {
+ final int err = gl.glGetError();
+ if( GL.GL_NO_ERROR != err ) {
+ throw new RuntimeException("Couldn't create TexImage2D RGBA "+width+"x"+height+", err "+toHexString(err));
+ }
+ }
+ gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
+ gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
+ // Clamp to edge is only option.
+ gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE);
+ gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE);
+
+ return com.jogamp.opengl.util.texture.TextureIO.newTexture(tex[idx],
+ textureTarget,
+ width, height,
+ width, height,
+ mustFlipVertically);
+ }
+
+ protected void destroyTexImage(GLContext ctx, TextureFrame imgTex) {
+ imgTex.getTexture().destroy(ctx.getGL());
+ }
+
+ protected void removeAllImageTextures(GLContext ctx) {
+ texture = null;
+ for(int i=0; i<textureCount; i++) {
+ final TextureFrame imgTex = texFrames[i];
+ destroyTexImage(ctx, imgTex);
+ texFrames[i] = null;
+ }
+ texFrameMap.clear();
+ }
+
+ protected void attributesUpdated(int event_mask) {
+ synchronized(eventListenersLock) {
+ for(Iterator<GLMediaEventListener> i = eventListeners.iterator(); i.hasNext(); ) {
+ i.next().attributesChanges(this, event_mask);
+ }
+ }
+ }
+ protected void newFrameAvailable(TextureFrame frame) {
+ synchronized(eventListenersLock) {
+ for(Iterator<GLMediaEventListener> i = eventListeners.iterator(); i.hasNext(); ) {
+ i.next().newFrameAvailable(this, frame);
+ }
+ }
+ }
+
+ @Override
+ public synchronized float getPlaySpeed() {
+ return playSpeed;
+ }
+
+ @Override
+ public synchronized Texture getLastTextureID() {
+ return texture;
+ }
+
+ @Override
+ public synchronized void destroy(GL gl) {
+ destroyImpl(gl);
+ removeAllImageTextures(gl.getContext());
+ }
+ protected abstract void destroyImpl(GL gl);
+
+ @Override
+ public synchronized URL getURL() {
+ return url;
+ }
+
+ @Override
+ public synchronized String getVideoCodec() {
+ return vcodec;
+ }
+
+ @Override
+ public synchronized String getAudioCodec() {
+ return acodec;
+ }
+
+ @Override
+ public synchronized long getTotalFrames() {
+ return totalFrames;
+ }
+
+ @Override
+ public synchronized long getBitrate() {
+ return bps;
+ }
+
+ @Override
+ public synchronized int getFramerate() {
+ return fps;
+ }
+
+ @Override
+ public synchronized int getWidth() {
+ return width;
+ }
+
+ @Override
+ public synchronized int getHeight() {
+ return height;
+ }
+
+ @Override
+ public synchronized String toString() {
+ return "GLMediaPlayer [ stream [ video [ "+vcodec+", "+width+"x"+height+", "+fps+"fps, "+bps+"bsp, "+totalFrames+"f ] ] ]";
+ }
+
+ @Override
+ public void addEventListener(GLMediaEventListener l) {
+ if(l == null) {
+ return;
+ }
+ synchronized(eventListenersLock) {
+ eventListeners.add(l);
+ }
+ }
+
+ @Override
+ public void removeEventListener(GLMediaEventListener l) {
+ if (l == null) {
+ return;
+ }
+ synchronized(eventListenersLock) {
+ eventListeners.remove(l);
+ }
+ }
+
+ @Override
+ public synchronized GLMediaEventListener[] getEventListeners() {
+ synchronized(eventListenersLock) {
+ return eventListeners.toArray(new GLMediaEventListener[eventListeners.size()]);
+ }
+ }
+
+ private Object eventListenersLock = new Object();
+
+ protected static final String toHexString(long v) {
+ return "0x"+Long.toHexString(v);
+ }
+ protected static final String toHexString(int v) {
+ return "0x"+Integer.toHexString(v);
+ }
+
+} \ No newline at end of file
diff --git a/src/jogl/classes/jogamp/opengl/omx/OMXGLMediaPlayer.java b/src/jogl/classes/jogamp/opengl/omx/OMXGLMediaPlayer.java
new file mode 100644
index 000000000..8f5f9c3ab
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/omx/OMXGLMediaPlayer.java
@@ -0,0 +1,238 @@
+
+package jogamp.opengl.omx;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLException;
+
+import com.jogamp.opengl.av.GLMediaEventListener;
+import com.jogamp.opengl.util.texture.Texture;
+
+import jogamp.opengl.av.EGLMediaPlayerImpl;
+import jogamp.opengl.egl.EGL;
+
+public class OMXGLMediaPlayer extends EGLMediaPlayerImpl {
+ 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;
+
+ public OMXGLMediaPlayer() {
+ super(TextureType.KHRImage, true);
+ initOMX();
+ }
+
+ protected void initOMX() {
+ moviePtr = _createInstance();
+ if(0==moviePtr) {
+ throw new GLException("Couldn't create OMXInstance");
+ }
+ }
+
+ @Override
+ protected TextureFrame createTexImage(GLContext ctx, int idx, int[] tex) {
+ final EGLTextureFrame eglTex = (EGLTextureFrame) super.createTexImage(ctx, idx, tex);
+ _setStreamEGLImageTexture2D(moviePtr, idx, tex[idx], eglTex.getImage(), eglTex.getSync());
+ return eglTex;
+ }
+
+ @Override
+ protected void destroyTexImage(GLContext ctx, TextureFrame imgTex) {
+ super.destroyTexImage(ctx, imgTex);
+ }
+
+ @Override
+ protected void destroyImpl(GL gl) {
+ _detachVideoRenderer(moviePtr);
+ if (moviePtr != 0) {
+ _destroyInstance(moviePtr);
+ moviePtr = 0;
+ }
+ }
+
+ @Override
+ protected void setStreamImpl() throws IOException {
+ if(0==moviePtr) {
+ throw new GLException("OMX native instance null");
+ }
+ String path=null;
+ if (url.getProtocol() == null || "file".equals(url.getProtocol())) {
+ // CV only accepts absolute paths
+ try {
+ File file = new File(url.getPath());
+ if (!file.exists()) {
+ throw new FileNotFoundException(file.toString());
+ }
+ path = file.getCanonicalPath();
+ System.out.println("setURL: path "+path);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new IOException(e);
+ }
+ }
+ path = replaceAll(path, "\\", "/").trim();
+ if(null==path) {
+ throw new IOException("Couldn't parse stream URL: "+url);
+ }
+ System.out.println("setURL: clean path "+path);
+
+ System.out.println("setURL: p1 "+this);
+ _setStream(moviePtr, textureCount, path);
+ System.out.println("setURL: p2 "+this);
+ }
+
+
+ @Override
+ public synchronized int getCurrentPosition() {
+ if(0==moviePtr) {
+ throw new GLException("OMX native instance null");
+ }
+ return _getCurrentPosition(moviePtr);
+ }
+
+ @Override
+ public synchronized boolean isValid() {
+ return (moviePtr != 0);
+ }
+
+ @Override
+ public synchronized void setPlaySpeed(float rate) {
+ if(0==moviePtr) {
+ throw new GLException("OMX native instance null");
+ }
+ _setPlaySpeed(moviePtr, rate);
+ playSpeed = rate;
+ }
+
+ /** @return time position after issuing the command */
+ @Override
+ public synchronized void start() {
+ if(0==moviePtr) {
+ throw new GLException("OMX native instance null");
+ }
+ _play(moviePtr);
+ }
+
+ /** @return time position after issuing the command */
+ @Override
+ public synchronized void pause() {
+ if(0==moviePtr) {
+ throw new GLException("OMX native instance null");
+ }
+ _pause(moviePtr);
+ }
+
+ /** @return time position after issuing the command */
+ @Override
+ public synchronized void stop() {
+ if(0==moviePtr) {
+ throw new GLException("OMX native instance null");
+ }
+ _stop(moviePtr);
+ }
+
+ /** @return time position after issuing the command */
+ @Override
+ public synchronized int seek(int msec) {
+ if(0==moviePtr) {
+ throw new GLException("OMX native instance null");
+ }
+ return _seek(moviePtr, msec);
+ }
+
+ @Override
+ public synchronized Texture getNextTextureID() {
+ if(0==moviePtr) {
+ throw new GLException("OMX native instance null");
+ }
+ texture=null;
+ TextureFrame eglImgTex = texFrameMap.get(new Integer(_getNextTextureID(moviePtr)));
+ if(null!=eglImgTex) {
+ texture = eglImgTex.getTexture();
+ }
+ return texture;
+ }
+
+ 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;
+ }
+
+ private String replaceAll(String orig, String search, String repl) {
+ String dest=null;
+ // In case replaceAll / java.util.regex.* is not supported (-> CVM)
+ int i=0,j;
+ dest = new String();
+ while((j=orig.indexOf(search, i))>=0) {
+ dest=dest.concat(orig.substring(i, j));
+ dest=dest.concat(repl);
+ i=j+1;
+ }
+ return dest.concat(orig.substring(i, orig.length()));
+ }
+
+ private void errorCheckEGL(String s) {
+ int e;
+ if( (e=EGL.eglGetError()) != EGL.EGL_SUCCESS ) {
+ System.out.println("EGL Error: ("+s+"): 0x"+Integer.toHexString(e));
+ }
+ }
+
+ //
+ // OMXEventListener Support
+ //
+
+ native long _createInstance();
+ 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);
+
+ native void _setStreamEGLImageTexture2D(long moviePtr, int i, int tex, long image, long sync);
+ native int _seek(long moviePtr, int position);
+ native void _setPlaySpeed(long moviePtr, float rate);
+ native void _play(long moviePtr);
+ native void _pause(long moviePtr);
+ native void _stop(long moviePtr);
+ native int _getNextTextureID(long moviePtr);
+ native int _getCurrentPosition(long moviePtr);
+}
+