/** * Copyright 2012 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of JogAmp Community. */ package jogamp.opengl.util.av; import java.io.IOException; import java.io.PrintStream; import java.net.URLConnection; import java.nio.ByteBuffer; import com.jogamp.opengl.GL; import com.jogamp.opengl.GLException; import com.jogamp.opengl.GLProfile; import com.jogamp.common.av.PTS; import com.jogamp.common.nio.Buffers; import com.jogamp.common.os.Clock; import com.jogamp.common.util.IOUtil; import com.jogamp.opengl.util.av.CodecID; import com.jogamp.opengl.util.av.GLMediaPlayer; import com.jogamp.opengl.util.texture.Texture; import com.jogamp.opengl.util.texture.TextureData; import com.jogamp.opengl.util.texture.TextureIO; import com.jogamp.opengl.util.texture.TextureSequence; /*** * A dummy null media player implementation using a static test frame * available on all platforms. */ public class NullGLMediaPlayer extends GLMediaPlayerImpl { private TextureData texData = null; private final PTS video_pts = new PTS( () -> { return State.Playing == getState() ? getPlaySpeed() : 0f; } ); public NullGLMediaPlayer() { super(); } @Override public final void printNativeInfo(final PrintStream out) { out.println("NullGLMediaPlayer: available true"); } @Override protected final boolean setPlaySpeedImpl(final float rate) { return false; } @Override protected final boolean resumeImpl() { video_pts.setSCR(Clock.currentMillis()); return true; } @Override protected final boolean pauseImpl() { return true; } @Override protected final void stopImpl() { } @Override protected final int seekImpl(final int msec) { video_pts.setPTS(msec); validatePos(); return msec; } @Override protected final int getNextTextureImpl(final GL gl, final TextureFrame vFrame, final Texture sTex, final boolean[] sTexUsed) { final int pts = getLastBufferedAudioPTS(); vFrame.setPTS( pts ); return pts; } @Override protected PTS getAudioPTSImpl() { return video_pts; } @Override protected final PTS getUpdatedAudioPTS() { validatePos(); return video_pts; } @Override protected int getAudioQueuedDuration() { return 0; } @Override protected int getLastBufferedAudioPTS() { return video_pts.getLast(); } @Override protected final void destroyImpl() { if(null != texData) { texData.destroy(); texData = null; } } public final static TextureData createTestTextureData() { TextureData res = null; try { final URLConnection urlConn = IOUtil.getResource("jogamp/opengl/assets/test-ntsc01-28x16.png", NullGLMediaPlayer.class.getClassLoader()); if(null != urlConn) { res = TextureIO.newTextureData(GLProfile.getGL2ES2(), urlConn.getInputStream(), false, TextureIO.PNG); } } catch (final Exception e) { e.printStackTrace(); } if(null == res) { final int w = 160; final int h = 90; final ByteBuffer buffer = Buffers.newDirectByteBuffer(w*h*4); while(buffer.hasRemaining()) { buffer.put((byte) 0xEA); buffer.put((byte) 0xEA); buffer.put((byte) 0xEA); buffer.put((byte) 0xEA); } buffer.rewind(); res = new TextureData(GLProfile.getGL2ES2(), GL.GL_RGBA, w, h, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, false, false, false, buffer, null); } return res; } @Override protected final void initStreamImpl(final int vid, final int aid, final int sid) throws IOException { texData = createTestTextureData(); final float _fps = 24f; final int _duration = 10*60*1000; // msec final int _totalFrames = (int) ( (_duration/1000)*_fps ); updateAttributes("null", new int[] { 0 }, new String[] { "und" }, 0 /* fake */, new int[0], new String[0], GLMediaPlayer.STREAM_ID_NONE, new int[0], new String[0], GLMediaPlayer.STREAM_ID_NONE, texData.getWidth(), texData.getHeight(), 0, 0, 0, _fps, _totalFrames, 0, _duration, "png-static", null, null, CodecID.toFFmpeg(CodecID.PNG), -1, -1); } @Override protected final void initGLImpl(final GL gl) throws IOException, GLException { setIsGLOriented(true); } /** * {@inheritDoc} *
* Returns {@link GLMediaPlayer#TEXTURE_COUNT_MIN}. *
*/ @Override protected int validateTextureCount(final int desiredTextureCount) { return TEXTURE_COUNT_MIN; } @Override protected final TextureSequence.TextureFrame createTexImage(final GL gl, final int texName) { final Texture texture = super.createTexImageImpl(gl, texName, getWidth(), getHeight()); if(null != texData) { texture.updateImage(gl, texData); } return new TextureSequence.TextureFrame( texture ); } @Override protected final void destroyTexFrame(final GL gl, final TextureSequence.TextureFrame frame) { super.destroyTexFrame(gl, frame); } private void validatePos() { boolean considerPausing = false; if( 0 > video_pts.getLast() ) { video_pts.setPTS(0); considerPausing = true; } else if ( video_pts.getLast() > getDuration() ) { video_pts.setPTS( getDuration() ); considerPausing = true; } if( considerPausing && State.Playing == getState() ) { setState(State.Paused); } } }