package jogamp.opengl.omx; import java.io.IOException; import java.net.URL; import javax.media.opengl.GL; import javax.media.opengl.GLException; import com.jogamp.opengl.av.GLMediaEventListener; import com.jogamp.opengl.util.texture.TextureCoords; 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; protected long o_duration = 0; protected TextureFrame lastTex = null; 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(GL gl, int idx, int[] tex) { final EGLTextureFrame eglTex = (EGLTextureFrame) super.createTexImage(gl, idx, tex); _setStreamEGLImageTexture2D(moviePtr, idx, tex[idx], eglTex.getImage(), eglTex.getSync()); lastTex = eglTex; return eglTex; } @Override protected void destroyTexImage(GL gl, TextureFrame imgTex) { super.destroyTexImage(gl, imgTex); } @Override protected void destroyImpl(GL gl) { _detachVideoRenderer(moviePtr); if (moviePtr != 0) { _destroyInstance(moviePtr); moviePtr = 0; } } @Override protected void initGLStreamImpl(GL gl, int[] texNames) throws IOException { if(0==moviePtr) { throw new GLException("OMX native instance null"); } final URL url = urlConn.getURL(); if(!url.getProtocol().equals("file")) { throw new IOException("Only file URLs are allowed: "+url); } final String path=url.getPath(); 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 long getCurrentPosition() { if(0==moviePtr) { throw new GLException("OMX native instance null"); } return _getCurrentPosition(moviePtr); } @Override public synchronized void setPlaySpeed(float rate) { if(0==moviePtr) { throw new GLException("OMX native instance null"); } _setPlaySpeed(moviePtr, rate); playSpeed = rate; } @Override public synchronized boolean startImpl() { if(0==moviePtr) { return false; } _play(moviePtr); return true; } /** @return time position after issuing the command */ @Override public synchronized boolean pauseImpl() { if(0==moviePtr) { return false; } _pause(moviePtr); return true; } /** @return time position after issuing the command */ @Override public synchronized boolean stopImpl() { if(0==moviePtr) { return false; } _stop(moviePtr); return true; } /** @return time position after issuing the command */ @Override protected long seekImpl(long msec) { if(0==moviePtr) { throw new GLException("OMX native instance null"); } return _seek(moviePtr, msec); } @Override public TextureFrame getLastTexture() { return lastTex; } @Override public synchronized TextureFrame getNextTexture(GL gl, boolean blocking) { if(0==moviePtr) { throw new GLException("OMX native instance null"); } final int nextTex = _getNextTextureID(moviePtr, blocking); if(0 < nextTex) { final TextureFrame eglImgTex = texFrameMap.get(new Integer(_getNextTextureID(moviePtr, blocking))); if(null!=eglImgTex) { lastTex = eglImgTex; } } return lastTex; } @Override public TextureCoords getTextureCoords() { return lastTex.getTexture().getImageTexCoords(); } 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) 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 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); }