From 5911b729b69b7fb327e441b33f22eb1ef31a03df Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Mon, 2 Apr 2012 08:36:38 +0200 Subject: 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. --- .../com/jogamp/opengl/av/GLMediaEventListener.java | 17 + .../com/jogamp/opengl/av/GLMediaPlayer.java | 90 ++++ .../com/jogamp/opengl/av/GLMediaPlayerFactory.java | 18 + .../com/jogamp/openmax/OMXEventListener.java | 14 - .../classes/com/jogamp/openmax/OMXInstance.java | 509 --------------------- 5 files changed, 125 insertions(+), 523 deletions(-) create mode 100644 src/jogl/classes/com/jogamp/opengl/av/GLMediaEventListener.java create mode 100644 src/jogl/classes/com/jogamp/opengl/av/GLMediaPlayer.java create mode 100644 src/jogl/classes/com/jogamp/opengl/av/GLMediaPlayerFactory.java delete mode 100644 src/jogl/classes/com/jogamp/openmax/OMXEventListener.java delete mode 100644 src/jogl/classes/com/jogamp/openmax/OMXInstance.java (limited to 'src/jogl/classes/com/jogamp') 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: + * + */ +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; itex ) { - 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