From 6332e13b2f0aa9818d37802302f04c90a4fa4239 Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Sat, 10 Aug 2013 09:14:19 +0200
Subject: GLMediaPlayer: Add multithreaded decoding w/ textureCount > 2 where
available EGL/FFMPeg. WIP!
Off-thread decoding:
If validated (impl) textureCount > 2, decoding happens on extra thread.
If decoding requires GL context, a shared context is created for decoding thread.
API Changes:
- initGLStream(..): Adds 'textureCount' as argument.
- TextureSequence.TexSeqEventListener.newFrameAvailable(..) exposes the new frame available
- TextureSequence.TextureFrame exposes the PTS (video)
Implementation:
- 'int validateTextureCount(int)': implementation decides whether textureCount can be > 2, i.e. off-thread decoding allowed,
default is NO w/ textureCount==2!
- 'boolean requiresOffthreadGLCtx()': implementation decides whether shared context is required for off-thread decoding
- 'syncFrame2Audio(TextureFrame frame)': implementation shall handle a/v sync, due to audio stream details (pts, buffered frames)
- FFMPEGMediaPlayer extends GLMediaPlayerImpl, no more EGLMediaPlayerImpl (redundant)
+++
- SyncedRingbuffer: Expose T[] array
+++
TODO:
- syncAV!
- test Android
---
.../com/jogamp/opengl/util/av/GLMediaPlayer.java | 35 +++++++++++++++-------
.../opengl/util/av/GLMediaPlayerFactory.java | 8 +++--
.../opengl/util/texture/TextureSequence.java | 17 ++++++++---
3 files changed, 43 insertions(+), 17 deletions(-)
(limited to 'src/jogl/classes/com/jogamp/opengl/util')
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 1825dbd47..a36bce305 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java
@@ -40,12 +40,12 @@ import com.jogamp.opengl.util.texture.TextureSequence;
/**
* Lifecycle of an GLMediaPlayer:
*
- * action | state before | state after |
- * {@link #initGLStream(GL, URLConnection)} | Uninitialized | Stopped |
- * {@link #start()} | Stopped, Paused | Playing |
- * {@link #stop()} | Playing, Paused | Stopped |
- * {@link #pause()} | Playing | Paused |
- * {@link #destroy(GL)} | ANY | Uninitialized |
+ * action | state before | state after |
+ * {@link #initGLStream(GL, int, URLConnection)} | Uninitialized | Stopped |
+ * {@link #start()} | Stopped, Paused | Playing |
+ * {@link #stop()} | Playing, Paused | Stopped |
+ * {@link #pause()} | Playing | Paused |
+ * {@link #destroy(GL)} | ANY | Uninitialized |
*
*
* Current implementations (check each API doc link for details):
@@ -105,8 +105,12 @@ public interface GLMediaPlayer extends TextureSequence {
public int getTextureCount();
- /** Defaults to 0 */
+ /** Returns the texture target used by implementation. */
+ public int getTextureTarget();
+
+ /** Sets the texture unit. Defaults to 0. */
public void setTextureUnit(int u);
+
/** Sets the texture min-mag filter, defaults to {@link GL#GL_NEAREST}. */
public void setTextureMinMagFilter(int[] minMagFilter);
/** Sets the texture min-mag filter, defaults to {@link GL#GL_CLAMP_TO_EDGE}. */
@@ -119,6 +123,7 @@ public interface GLMediaPlayer extends TextureSequence {
* Uninitialized -> Stopped
*
* @param gl current GL object. If null, no video output and textures will be available.
+ * @param textureCount desired number of buffered textures to be decoded off-thread, use 1
for on-thread decoding.
* @param urlConn the stream connection
* @return the new state
*
@@ -126,7 +131,7 @@ public interface GLMediaPlayer extends TextureSequence {
* @throws IOException in case of difficulties to open or process the stream
* @throws GLException in case of difficulties to initialize the GL resources
*/
- public State initGLStream(GL gl, URLConnection urlConn) throws IllegalStateException, GLException, IOException;
+ public State initGLStream(GL gl, int textureCount, URLConnection urlConn) throws IllegalStateException, GLException, IOException;
/**
* Releases the GL and stream resources.
@@ -161,10 +166,20 @@ public interface GLMediaPlayer extends TextureSequence {
public State getState();
/**
- * @return time current position in milliseconds
+ * @return current streaming position in milliseconds
**/
public int getCurrentPosition();
+ /**
+ * @return current video PTS in milliseconds of {@link #getLastTexture()}
+ **/
+ public int getVideoPTS();
+
+ /**
+ * @return current audio PTS in milliseconds.
+ **/
+ public int getAudioPTS();
+
/**
* Allowed in state Stopped, Playing and Paused, otherwise ignored.
*
@@ -187,7 +202,7 @@ public interface GLMediaPlayer extends TextureSequence {
*
*
* @see #addEventListener(GLMediaEventListener)
- * @see GLMediaEventListener#newFrameAvailable(GLMediaPlayer, long)
+ * @see GLMediaEventListener#newFrameAvailable(GLMediaPlayer, TextureFrame, long)
*/
@Override
public TextureSequence.TextureFrame getNextTexture(GL gl, boolean blocking) throws IllegalStateException;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayerFactory.java b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayerFactory.java
index f09531f7f..2707dd6d2 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayerFactory.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayerFactory.java
@@ -29,18 +29,20 @@ package com.jogamp.opengl.util.av;
import jogamp.opengl.util.av.NullGLMediaPlayer;
-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";
private static final String FFMPEGMediaPlayerClazzName = "jogamp.opengl.util.av.impl.FFMPEGMediaPlayer";
+ private static final String OMXGLMediaPlayerClazzName = "jogamp.opengl.util.av.impl.OMXGLMediaPlayer";
private static final String isAvailableMethodName = "isAvailable";
public static GLMediaPlayer createDefault() {
final ClassLoader cl = GLMediaPlayerFactory.class.getClassLoader();
- GLMediaPlayer sink = create(cl, AndroidGLMediaPlayerAPI14ClazzName);
+ GLMediaPlayer sink = create(cl, OMXGLMediaPlayerClazzName);
+ if( null == sink ) {
+ sink = create(cl, AndroidGLMediaPlayerAPI14ClazzName);
+ }
if( null == sink ) {
sink = create(cl, FFMPEGMediaPlayerClazzName);
}
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 9f951d5da..3f739b2cc 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java
@@ -112,26 +112,35 @@ public interface TextureSequence {
public static class TextureFrame {
public TextureFrame(Texture t) {
texture = t;
+ pts = 0;
}
public final Texture getTexture() { return texture; }
+ public final int getPTS() { return pts; }
+ public final void setPTS(int pts) { this.pts = pts; }
public String toString() {
- return "TextureFrame[" + texture + "]";
+ return "TextureFrame[" + pts + "ms: " + texture + "]";
}
protected final Texture texture;
+ protected int pts;
}
public interface TexSeqEventListener {
/**
- * Signaling listeners that {@link TextureSequence#getNextTexture(GL, boolean)} is able to deliver a new frame.
+ * Signaling listeners that a new {@link TextureFrame} is available.
+ *
+ * User shall utilize {@link TextureSequence#getNextTexture(GL, boolean)} to dequeue it to maintain
+ * a consistent queue.
+ *
* @param ts the event source
+ * @param newFrame the newly enqueued frame
* @param when system time in msec.
**/
- public void newFrameAvailable(T ts, long when);
+ public void newFrameAvailable(T ts, TextureFrame newFrame, long when);
}
- /** Return the texture unit to be used with this frame. */
+ /** Return the texture unit used to render the current frame. */
public int getTextureUnit();
public int[] getTextureMinMagFilter();
--
cgit v1.2.3