aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/jogamp/opengl
diff options
context:
space:
mode:
Diffstat (limited to 'src/jogl/classes/jogamp/opengl')
-rw-r--r--src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java8
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java219
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/NullGLMediaPlayer.java7
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java83
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java56
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java14
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGStaticNatives.java2
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv0400Natives.java9
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv0500Natives.java9
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv0600Natives.java9
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java7
11 files changed, 322 insertions, 101 deletions
diff --git a/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java b/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java
index c4d1ee78f..0924bb67e 100644
--- a/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java
+++ b/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java
@@ -341,7 +341,7 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl {
r_aids, r_alangs, r_aid,
new int[0], new String[0], GLMediaPlayer.STREAM_ID_NONE,
mp.getVideoWidth(), mp.getVideoHeight(), 0, 0, 0, 0f, 0, 0, mp.getDuration(),
- icodec, icodec, null);
+ icodec, icodec, null, -1, -1, -1);
/**
mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
@@ -379,7 +379,7 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl {
new int[0], new String[0], GLMediaPlayer.STREAM_ID_NONE,
new int[0], new String[0], GLMediaPlayer.STREAM_ID_NONE,
size.width, size.height, 0, 0, 0, fpsRange[1]/1000f, 0, 0, 0,
- icodec, icodec, null);
+ icodec, icodec, null, -1, -1, -1);
}
}
private static String camSz2Str(final Camera.Size csize) {
@@ -406,10 +406,10 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl {
}
@Override
- protected final int getNextTextureImpl(final GL gl, final TextureFrame nextFrame) throws InterruptedException {
+ protected final int getNextTextureImpl(final GL gl, final TextureFrame vFrame, Texture sTex, boolean[] sTexUsed) throws InterruptedException {
int pts = TimeFrameI.INVALID_PTS;
if(null != mp || null != cam) {
- final SurfaceTextureFrame sTexFrame = null != nextFrame ? (SurfaceTextureFrame) nextFrame : singleSTexFrame;
+ final SurfaceTextureFrame sTexFrame = null != vFrame ? (SurfaceTextureFrame) vFrame : singleSTexFrame;
final SurfaceTexture surfTex = sTexFrame.surfaceTex;
if( !sTexFrameAttached ) {
sTexFrameAttached = true;
diff --git a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java
index 219cfb3e5..a52efe2ac 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java
@@ -64,13 +64,15 @@ import com.jogamp.common.util.Ringbuffer;
import com.jogamp.common.util.TSPrinter;
import com.jogamp.common.util.WorkerThread;
import com.jogamp.math.FloatUtil;
+import com.jogamp.math.Vec2i;
+import com.jogamp.math.Vec4f;
import com.jogamp.opengl.GLExtensions;
import com.jogamp.opengl.util.av.SubtitleEventListener;
+import com.jogamp.opengl.util.av.CodecID;
import com.jogamp.opengl.util.av.GLMediaPlayer;
-import com.jogamp.opengl.util.av.SubASSEventLine;
+import com.jogamp.opengl.util.av.SubTextEvent;
import com.jogamp.opengl.util.av.SubEmptyEvent;
-import com.jogamp.opengl.util.av.SubTextureEvent;
-import com.jogamp.opengl.util.av.SubtitleEvent;
+import com.jogamp.opengl.util.av.SubBitmapEvent;
import com.jogamp.opengl.util.glsl.ShaderCode;
import com.jogamp.opengl.util.texture.Texture;
import com.jogamp.opengl.util.texture.TextureData;
@@ -178,6 +180,12 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
/** In ms. Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
private int duration = 0;
/** Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+ private CodecID acodecID = CodecID.NONE;
+ /** Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+ private CodecID vcodecID = CodecID.NONE;
+ /** Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+ private CodecID scodecID = CodecID.NONE;
+ /** Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
private String acodec = unknown;
/** Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
private String vcodec = unknown;
@@ -238,6 +246,11 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
private Ringbuffer<TextureFrame> videoFramesFree = null;
private Ringbuffer<TextureFrame> videoFramesDecoded = null;
private volatile TextureFrame lastFrame = null;
+ private Texture[] subTexOrig = null;
+ private Ringbuffer<Texture> subTexFree = null;
+ private static final int SUB_TEX_IMAGES_MIN = TEXTURE_COUNT_MIN + 1;
+ private static final boolean subDEBUG = true;
+
/**
* @see #isGLOriented()
*/
@@ -387,12 +400,12 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
public final PTS getPTS() { return av_scr_cpy; }
@Override
- public final int getVideoPTS() { return video_pts_last.get(Clock.currentMillis()); }
+ public final int getVideoPTS() { return video_pts_last.getCurrent(); }
@Override
public final int getAudioPTS() {
if( State.Uninitialized != state && null != audioSink ) {
- return audioSink.getPTS().get(Clock.currentMillis());
+ return audioSink.getPTS().getCurrent();
}
return 0;
}
@@ -746,9 +759,9 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
}
/**
* Implementation shall set the following set of data here
- * @param sid TODO
* @see #vid
* @see #aid
+ * @see #sid
* @see #width
* @see #height
* @see #fps
@@ -821,11 +834,20 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
videoFramesDecoded = new LFRingbuffer<TextureFrame>(TextureFrame[].class, textureCount);
lastFrame = videoFramesFree.getBlocking();
}
+ if( STREAM_ID_NONE != sid ) {
+ subTexOrig = createSubTextures(gl, Math.max(SUB_TEX_IMAGES_MIN, textureCount)); // minimum 2 textures
+ subTexFree = new LFRingbuffer<Texture>(subTexOrig);
+ } else {
+ subTexOrig = null;
+ subTexFree = null;
+ }
} else {
videoFramesOrig = null;
videoFramesFree = null;
videoFramesDecoded = null;
lastFrame = null;
+ subTexOrig = null;
+ subTexFree = null;
}
if( null == streamWorker &&
( TEXTURE_COUNT_MIN < textureCount || STREAM_ID_NONE == vid ) ) // Enable StreamWorker for 'audio only' as well (Bug 918).
@@ -848,6 +870,8 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
videoFramesFree = null;
videoFramesDecoded = null;
lastFrame = null;
+ subTexOrig = null;
+ subTexFree = null;
} else {
// Using a dummy test frame
width = TestTexture.singleton.getWidth();
@@ -865,6 +889,8 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
videoFramesDecoded = new LFRingbuffer<TextureFrame>(TextureFrame[].class, textureCount);
lastFrame = videoFramesFree.getBlocking( );
}
+ subTexOrig = null;
+ subTexFree = null;
// changeState(0, State.Paused);
}
} catch (final Throwable t) {
@@ -924,6 +950,20 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
}
return texFrames;
}
+ protected Texture[] createSubTextures(final GL gl, final int count) {
+ final int[] texNames = new int[count];
+ gl.glGenTextures(count, texNames, 0);
+ final int err = gl.glGetError();
+ if( GL.GL_NO_ERROR != err ) {
+ throw new RuntimeException("TextureNames creation failed (num: "+count+"): err "+toHexString(err));
+ }
+ final Texture[] textures = new Texture[count];
+ for(int i=0; i<count; i++) {
+ textures[i] = new Texture(texNames[i], true /* ownsTextureID */,
+ textureTarget, 1, 1, 1, 1, true);
+ }
+ return textures;
+ }
private static class TestTexture {
private static final TextureData singleton;
@@ -968,7 +1008,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
new int[0], new String[0], GLMediaPlayer.STREAM_ID_NONE,
new int[0], new String[0], GLMediaPlayer.STREAM_ID_NONE,
TestTexture.singleton.getWidth(), TestTexture.singleton.getHeight(), 0, 0, 0, _fps, _totalFrames, 0, _duration,
- "png-static", null, null);
+ "png-static", null, null, CodecID.toFFmpeg(CodecID.PNG), -1, -1);
}
protected abstract TextureFrame createTexImage(GL gl, int texName);
@@ -1063,11 +1103,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
return lastFrame;
}
- private final void removeAllTextureFrames(final GL gl) {
- final TextureFrame[] texFrames = videoFramesOrig;
- videoFramesOrig = null;
- videoFramesFree = null;
- videoFramesDecoded = null;
+ private final void destroyTexFrames(final GL gl, final TextureFrame[] texFrames) {
if( null != texFrames ) {
for(int i=0; i<texFrames.length; i++) {
final TextureFrame frame = texFrames[i];
@@ -1083,6 +1119,36 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
}
}
}
+ private final void destroyTextures(final GL gl, final Texture[] textures) {
+ if( null != textures ) {
+ for(int i=0; i<textures.length; i++) {
+ final Texture tex = textures[i];
+ if(null != tex) {
+ if( null != gl ) {
+ tex.destroy(gl);
+ }
+ textures[i] = null;
+ }
+ if( DEBUG ) {
+ logout.println(Thread.currentThread().getName()+"> Clear Texture["+i+"]: "+tex+" -> null");
+ }
+ }
+ }
+ }
+ private final void removeAllTextureFrames(final GL gl) {
+ destroyTexFrames(gl, videoFramesOrig);
+ videoFramesOrig = null;
+ videoFramesFree = null;
+ videoFramesDecoded = null;
+ lastFrame = null;
+ cachedFrame = null;
+ if( subDEBUG ) {
+ System.err.println("GLMediaPlayer: removeAllTextureFrames: subTexFree "+subTexFree);
+ }
+ destroyTextures(gl, subTexOrig); // can crash, if event obj w/ texture-copy still in use
+ subTexOrig = null;
+ subTexFree = null;
+ }
private TextureFrame cachedFrame = null;
private long lastMillis = 0;
@@ -1357,35 +1423,47 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
* Audio frames shall be ignored, if {@link #getAID()} is {@link #STREAM_ID_NONE}.
* </p>
* <p>
+ * Subtitle frames shall be ignored, if {@link #getSID()} is {@link #STREAM_ID_NONE}.
+ * </p>
+ * <p>
* Method may be invoked on the <a href="#streamworker"><i>StreamWorker</i> decoding thread</a>.
* </p>
* <p>
* Implementation shall care of OpenGL synchronization as required, e.g. glFinish()/glFlush()!
* </p>
* @param gl valid and current GL instance, shall be <code>null</code> for audio only.
- * @param nextFrame the {@link TextureFrame} to store the video PTS and texture data,
- * shall be <code>null</code> for audio only.
+ * @param vFrame next video {@link TextureFrame} to store the video PTS and texture data,
+ * shall be <code>null</code> for audio only.
+ * @param sTex {@link Texture} instance as bitmap subtitle target element.
+ * May be {@code null} for no desired bitmap subtitle.
+ * @param sTexUsed Result value. If the {@link Texture} {@code sTex} is used and {@link #pushSubtitleTex(Object, int, int, int, int, int, int, int, int, int, int)},
+ * {@code true} must be written into {@code sTexUsed}
* @return the last processed video PTS value, maybe {@link TimeFrameI#INVALID_PTS} if video frame is invalid or n/a.
* Will be {@link TimeFrameI#END_OF_STREAM_PTS} if end of stream reached.
* @throws InterruptedException if waiting for next frame fails
*/
- protected abstract int getNextTextureImpl(GL gl, TextureFrame nextFrame) throws InterruptedException;
+ protected abstract int getNextTextureImpl(GL gl, TextureFrame vFrame, Texture sTex, boolean[] sTexUsed) throws InterruptedException;
- protected final int getNextSingleThreaded(final GL gl, final TextureFrame nextFrame, final boolean[] gotVFrame) throws InterruptedException {
+ protected final int getNextSingleThreaded(final GL gl, final TextureFrame nextVFrame, final boolean[] gotVFrame) throws InterruptedException {
final int pts;
if( STREAM_ID_NONE != vid ) {
preNextTextureImpl(gl);
- pts = getNextTextureImpl(gl, nextFrame);
+ final boolean[] sTexUsed = { false };
+ final Texture subTex = ( null != subTexFree && STREAM_ID_NONE != sid ) ? subTexFree.get() : null;
+ pts = getNextTextureImpl(gl, nextVFrame, subTex, sTexUsed);
postNextTextureImpl(gl);
+ if( null != subTex && !sTexUsed[0] ) {
+ subTexFree.putBlocking(subTex); // return unused
+ }
if( TimeFrameI.INVALID_PTS != pts ) {
- newFrameAvailable(nextFrame, Clock.currentMillis());
+ newFrameAvailable(nextVFrame, Clock.currentMillis());
gotVFrame[0] = true;
} else {
gotVFrame[0] = false;
}
} else {
// audio only
- pts = getNextTextureImpl(null, null);
+ pts = getNextTextureImpl(null, null, null, null);
gotVFrame[0] = false;
}
return pts;
@@ -1603,6 +1681,8 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
private final WorkerThread.Callback action = (final WorkerThread self) -> {
final GL gl;
TextureFrame nextFrame = null;
+ final boolean[] subTexUsed = { false };
+ Texture subTex = null;
try {
if( STREAM_ID_NONE != vid ) {
nextFrame = videoFramesFree.getBlocking();
@@ -1611,7 +1691,17 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
} else {
gl = null;
}
- final int vPTS = getNextTextureImpl(gl, nextFrame);
+ if( null != gl && STREAM_ID_NONE != sid && null != subTexFree ) {
+ subTex = subTexFree.getBlocking();
+ }
+ final int vPTS = getNextTextureImpl(gl, nextFrame, subTex, subTexUsed);
+ if( null != subTex ) {
+ if( !subTexUsed[0] ) {
+ subTexFree.putBlocking(subTex);// return unused
+ } else if( subDEBUG ) {
+ System.err.println("GLMediaPlayer: Consumed SubTex: sid "+sid+", free "+subTexFree+", subTex "+subTex);
+ }
+ }
boolean audioEOS = false;
if( TimeFrameI.INVALID_PTS != vPTS ) {
if( null != nextFrame ) {
@@ -1652,7 +1742,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
}
} finally {
if( null != nextFrame ) { // put back
- videoFramesFree.put(nextFrame);
+ videoFramesFree.putBlocking(nextFrame);
}
}
};
@@ -1688,19 +1778,28 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
}
protected final void pushSubtitleText(final String text, final int start_display_pts, final int end_display_pts) {
if( null != subEventListener ) {
- subEventListener.run( new SubASSEventLine(SubtitleEvent.Format.ASS_TEXT, text, start_display_pts, end_display_pts) );
+ subEventListener.run( new SubTextEvent(this.scodecID, SubTextEvent.TextFormat.TEXT, text, start_display_pts, end_display_pts) );
}
}
protected final void pushSubtitleASS(final String ass, final int start_display_pts, final int end_display_pts) {
if( null != subEventListener ) {
- subEventListener.run( new SubASSEventLine(SubtitleEvent.Format.ASS_FFMPEG, ass, start_display_pts, end_display_pts) );
+ subEventListener.run( new SubTextEvent(this.scodecID, SubTextEvent.TextFormat.ASS, ass, start_display_pts, end_display_pts) );
}
}
- private final SubTextureEvent.TextureOwner subTexRelease = new SubTextureEvent.TextureOwner() {
+ /** {@link GLMediaPlayerImpl#pushSubtitleTex(Object, int, int, int, int, int, int, int, int, int)} */
+ private final SubBitmapEvent.TextureOwner subTexRelease = new SubBitmapEvent.TextureOwner() {
@Override
- public void release(final Texture tex) {
- if( null != subTexFree && null != tex ) { // put back
- subTexFree.put(tex);
+ public void release(final Texture subTex) {
+ if( null != subTexFree && null != subTex ) {
+ // return unused
+ try {
+ subTexFree.putBlocking(subTex);
+ if( subDEBUG ) {
+ System.err.println("GLMediaPlayer: Released SubTex: sid "+sid+", free "+subTexFree+", subTex "+subTex);
+ }
+ } catch (final InterruptedException e) {
+ throw new InternalError("GLMediaPlayer.SubTexRelease: Release failed, all full: sid "+sid+", free "+subTexFree+", subTex "+subTex+", "+GLMediaPlayerImpl.this, e);
+ }
}
}
@@ -1709,15 +1808,15 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
final int x, final int y, final int width, final int height,
final int start_display_pts, final int end_display_pts)
{
+ final Texture subTex = (Texture)texObj;
+ if( null != subTex ) {
+ subTex.set(texWidth, texHeight, width, height);
+ }
if( null != subEventListener ) {
- final Texture tex = (Texture)texObj;
- if( null != tex ) {
- tex.set(texWidth, texHeight, width, height);
- }
- subEventListener.run( new SubTextureEvent(new Vec2i(x, y), new Vec2i(width, height), tex,
- start_display_pts, end_display_pts, subTexRelease) );
+ subEventListener.run( new SubBitmapEvent(this.scodecID, new Vec2i(x, y), new Vec2i(width, height),
+ subTex, start_display_pts, end_display_pts, subTexRelease) );
} else {
- subTexRelease.release((Texture)texObj); // release right away
+ subTexRelease.release(subTex); // release right away
}
}
@@ -1779,13 +1878,15 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
* </p>
*/
protected final void updateAttributes(final String title,
- final int[] v_streams, final String[] v_langs,
- int vid, final int[] a_streams, final String[] a_langs,
- int aid, final int[] s_streams, final String[] s_langs,
- int sid, final int width, final int height,
+ final int[] v_streams, final String[] v_langs, int vid,
+ final int[] a_streams, final String[] a_langs, int aid,
+ final int[] s_streams, final String[] s_langs, int sid,
+ final int width, final int height,
final int bps_stream, final int bps_video, final int bps_audio,
final float fps, final int videoFrames, final int audioFrames, final int duration,
- final String vcodec, final String acodec, final String scodec) {
+ final String vcodec, final String acodec, final String scodec,
+ final int ffmpegVCodecID, final int ffmpegACodecID, final int ffmpegSCodecID)
+ {
final GLMediaPlayer.EventMask eventMask = new GLMediaPlayer.EventMask();
final boolean wasUninitialized = state == State.Uninitialized;
@@ -1878,16 +1979,37 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
}
if( (null!=acodec && acodec.length()>0 && !this.acodec.equals(acodec)) ) {
eventMask.setBit(GLMediaPlayer.EventMask.Bit.Codec);
+ eventMask.setBit(GLMediaPlayer.EventMask.Bit.ACodec);
this.acodec = acodec;
}
if( (null!=vcodec && vcodec.length()>0 && !this.vcodec.equals(vcodec)) ) {
eventMask.setBit(GLMediaPlayer.EventMask.Bit.Codec);
+ eventMask.setBit(GLMediaPlayer.EventMask.Bit.VCodec);
this.vcodec = vcodec;
}
if( (null!=scodec && scodec.length()>0 && !this.scodec.equals(scodec)) ) {
eventMask.setBit(GLMediaPlayer.EventMask.Bit.Codec);
+ eventMask.setBit(GLMediaPlayer.EventMask.Bit.SCodec);
this.scodec = scodec;
}
+ final CodecID acodecID = CodecID.fromFFmpeg(ffmpegACodecID);
+ final CodecID vcodecID = CodecID.fromFFmpeg(ffmpegVCodecID);
+ final CodecID scodecID = CodecID.fromFFmpeg(ffmpegSCodecID);
+ if( (0<ffmpegACodecID && CodecID.isAudioCodec(acodecID, true) && this.acodecID != acodecID) ) {
+ eventMask.setBit(GLMediaPlayer.EventMask.Bit.Codec);
+ eventMask.setBit(GLMediaPlayer.EventMask.Bit.ACodec);
+ this.acodecID = acodecID;
+ }
+ if( (0<ffmpegVCodecID && CodecID.isVideoCodec(vcodecID) && this.vcodecID != vcodecID) ) {
+ eventMask.setBit(GLMediaPlayer.EventMask.Bit.Codec);
+ eventMask.setBit(GLMediaPlayer.EventMask.Bit.VCodec);
+ this.vcodecID = vcodecID;
+ }
+ if( (0<ffmpegSCodecID && CodecID.isSubtitleCodec(scodecID) && this.scodecID != scodecID) ) {
+ eventMask.setBit(GLMediaPlayer.EventMask.Bit.Codec);
+ eventMask.setBit(GLMediaPlayer.EventMask.Bit.SCodec);
+ this.scodecID = scodecID;
+ }
if( eventMask.isZero() ) {
return;
}
@@ -2007,6 +2129,15 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
}
@Override
+ public final CodecID getVideoCodecID() { return vcodecID; }
+
+ @Override
+ public final CodecID getAudioCodecID() { return acodecID; }
+
+ @Override
+ public CodecID getSubtitleCodecID() { return scodecID; }
+
+ @Override
public final String getVideoCodec() { return vcodec; }
@Override
@@ -2069,18 +2200,18 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
@Override
public final String toString() {
- final String tt = PTS.millisToTimeStr(getDuration());
+ final String tt = PTS.toTimeStr(getDuration());
final String loc = ( null != streamLoc ) ? streamLoc.toString() : "<undefined stream>" ;
final int freeVideoFrames = null != videoFramesFree ? videoFramesFree.size() : 0;
final int decVideoFrames = null != videoFramesDecoded ? videoFramesDecoded.size() : 0;
- final int video_scr_ms = av_scr.get(Clock.currentMillis());
+ final int video_scr_ms = av_scr.getCurrent();
final String camPath = null != cameraPath ? ", camera: "+cameraPath : "";
return getClass().getSimpleName()+"["+state+", vSCR "+video_scr_ms+", "+getChapters().length+" chapters, duration "+tt+", frames[p "+presentedFrameCount+", d "+decodedFrameCount+", t "+videoFrames+", z "+nullFrameCount+" / "+maxNullFrameCountUntilEOS+"], "+
"speed "+playSpeed+", "+bps_stream+" bps, hasSW "+(null!=streamWorker)+
", Texture[count "+textureCount+", free "+freeVideoFrames+", dec "+decVideoFrames+", tagt "+toHexString(textureTarget)+", ifmt "+toHexString(textureInternalFormat)+", fmt "+toHexString(textureFormat)+", type "+toHexString(textureType)+"], "+
- "Video[id "+vid+"/"+Arrays.toString(v_streams)+"/"+Arrays.toString(v_langs)+", <"+vcodec+">, "+width+"x"+height+", glOrient "+isInGLOrientation+", "+fps+" fps, "+frame_duration+" fdur, "+bps_video+" bps], "+
- "Audio[id "+aid+"/"+Arrays.toString(a_streams)+"/"+Arrays.toString(a_langs)+", <"+acodec+">, "+bps_audio+" bps, "+audioFrames+" frames], "+
- "Subs[id "+sid+"/"+Arrays.toString(s_streams)+"/"+Arrays.toString(s_langs)+", <"+scodec+">], uri "+loc+camPath+"]";
+ "Video[id "+vid+"/"+Arrays.toString(v_streams)+"/"+Arrays.toString(v_langs)+", "+vcodecID+"/'"+vcodec+"', "+width+"x"+height+", glOrient "+isInGLOrientation+", "+fps+" fps, "+frame_duration+" fdur, "+bps_video+" bps], "+
+ "Audio[id "+aid+"/"+Arrays.toString(a_streams)+"/"+Arrays.toString(a_langs)+", "+acodecID+"/'"+acodec+"', "+bps_audio+" bps, "+audioFrames+" frames], "+
+ "Subs[id "+sid+"/"+Arrays.toString(s_streams)+"/"+Arrays.toString(s_langs)+", "+scodecID+"/'"+scodec+"'], uri "+loc+camPath+"]";
}
@Override
diff --git a/src/jogl/classes/jogamp/opengl/util/av/NullGLMediaPlayer.java b/src/jogl/classes/jogamp/opengl/util/av/NullGLMediaPlayer.java
index 44031372f..b8394dace 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/NullGLMediaPlayer.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/NullGLMediaPlayer.java
@@ -39,6 +39,7 @@ 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;
@@ -91,9 +92,9 @@ public class NullGLMediaPlayer extends GLMediaPlayerImpl {
}
@Override
- protected final int getNextTextureImpl(final GL gl, final TextureFrame nextFrame) {
+ protected final int getNextTextureImpl(final GL gl, final TextureFrame vFrame, final Texture sTex, final boolean[] sTexUsed) {
final int pts = getLastBufferedAudioPTS();
- nextFrame.setPTS( pts );
+ vFrame.setPTS( pts );
return pts;
}
@@ -154,7 +155,7 @@ public class NullGLMediaPlayer extends GLMediaPlayerImpl {
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);
+ "png-static", null, null, CodecID.toFFmpeg(CodecID.PNG), -1, -1);
}
@Override
protected final void initGLImpl(final GL gl) throws IOException, GLException {
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java
index cfe0f72af..e33822697 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java
@@ -52,14 +52,15 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
private static final List<String> glueLibNames = new ArrayList<String>(); // none
- private static final int symbolCount = 63;
+ private static final int symbolCount = 67;
private static final String[] symbolNames = {
"avutil_version",
"avformat_version",
"avcodec_version",
"avdevice_version", // (opt)
"swresample_version",
- /* 5 */
+ "swscale_version", // (opt)
+ /* 6 */
// libavcodec
"avcodec_close",
@@ -82,7 +83,7 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
"avcodec_receive_frame", // 57
"avcodec_decode_subtitle2", // 52.23.0
"avsubtitle_free", // 52.82.0
- /* +20 = 25 */
+ /* +20 = 26 */
// libavutil
"av_pix_fmt_desc_get", // >= lavu 51.45
@@ -102,7 +103,7 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
"av_channel_layout_uninit", // >= 59 (opt)
"av_channel_layout_describe", // >= 59 (opt)
"av_opt_set_chlayout", // >= 59
- /* +17 = 42 */
+ /* +17 = 43 */
// libavformat
"avformat_alloc_context",
@@ -119,11 +120,11 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
"avformat_network_init", // 53.13.0 (opt)
"avformat_network_deinit", // 53.13.0 (opt)
"avformat_find_stream_info", // 53.3.0 (opt)
- /* +14 = 56 */
+ /* +14 = 57 */
// libavdevice
"avdevice_register_all", // supported in all versions (opt)
- /* +1 = 57 */
+ /* +1 = 58 */
// libswresample
"av_opt_set_sample_fmt", // actually lavu .. but exist only w/ swresample!
@@ -132,7 +133,13 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
"swr_free",
"swr_convert",
"swr_get_out_samples",
- /* +6 = 63 */
+ /* +6 = 64 */
+
+ // libswscale
+ "sws_getCachedContext", // opt
+ "sws_scale", // opt
+ "sws_freeContext", // opt
+ /* +3 = 67 */
};
// optional symbol names
@@ -158,15 +165,22 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
"swr_free",
"swr_convert",
"swr_get_out_samples",
+
+ // libswscale
+ "swscale_version", // opt
+ "sws_getCachedContext", // opt
+ "sws_scale", // opt
+ "sws_freeContext", // opt
};
- /** 5: util, format, codec, device, swresample */
- private static final int LIB_COUNT = 5;
+ /** 6: util, format, codec, device, swresample, swscale */
+ private static final int LIB_COUNT = 6;
private static final int LIB_IDX_UTI = 0;
private static final int LIB_IDX_FMT = 1;
private static final int LIB_IDX_COD = 2;
private static final int LIB_IDX_DEV = 3;
private static final int LIB_IDX_SWR = 4;
+ private static final int LIB_IDX_SWS = 5;
/** util, format, codec, device, swresample */
private static final boolean[] libLoaded = new boolean[LIB_COUNT];
@@ -200,6 +214,7 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
static final VersionedLib avCodec;
static final VersionedLib avDevice;
static final VersionedLib swResample;
+ static final VersionedLib swScale;
private static final FFMPEGNatives natives;
private static final PrivilegedAction<DynamicLibraryBundle> privInitSymbolsAction = new PrivilegedAction<DynamicLibraryBundle>() {
@@ -226,7 +241,7 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
} };
/**
- * @param versions 5: util, format, codec, device, swresample
+ * @param versions 6: util, format, codec, device, swresample, swscale
* @return
*/
private static final boolean initSymbols(final VersionNumber[] versions, final List<NativeLibrary> nativeLibs) {
@@ -271,7 +286,11 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
versions[LIB_IDX_DEV] = new VersionNumber(0, 0, 0);
}
versions[LIB_IDX_SWR] = FFMPEGStaticNatives.getAVVersion(FFMPEGStaticNatives.getAvVersion0(symbolAddr[LIB_IDX_SWR]));
-
+ if( 0 != symbolAddr[LIB_IDX_SWS] ) {
+ versions[LIB_IDX_SWS] = FFMPEGStaticNatives.getAVVersion(FFMPEGStaticNatives.getAvVersion0(symbolAddr[LIB_IDX_SWS]));
+ } else {
+ versions[LIB_IDX_SWS] = new VersionNumber(0, 0, 0);
+ }
return res;
}
@@ -280,7 +299,7 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
GLProfile.initSingleton();
boolean _ready = false;
- /** 5: util, format, codec, device, swresample */
+ /** 6: util, format, codec, device, swresample, swscale */
final VersionNumber[] _versions = new VersionNumber[LIB_COUNT];
final List<NativeLibrary> _nativeLibs = new ArrayList<NativeLibrary>();
try {
@@ -294,6 +313,7 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
avCodec = new VersionedLib(_nativeLibs.get(LIB_IDX_COD), _versions[LIB_IDX_COD]);
avDevice = new VersionedLib(_nativeLibs.get(LIB_IDX_DEV), _versions[LIB_IDX_DEV]);
swResample = new VersionedLib(_nativeLibs.get(LIB_IDX_SWR), _versions[LIB_IDX_SWR]);
+ swScale = new VersionedLib(_nativeLibs.get(LIB_IDX_SWS), _versions[LIB_IDX_SWS]);
if(!libsCFUSLoaded) {
String missing = "";
if( !libLoaded[LIB_IDX_COD] ) {
@@ -321,13 +341,20 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
final int avCodecMajor = avCodec.version.getMajor();
final int avDeviceMajor = avDevice.version.getMajor();
final int swResampleMajor = swResample.version.getMajor();
- if( avCodecMajor == 58 && avFormatMajor == 58 && ( avDeviceMajor == 58 || avDeviceMajor == 0 ) && avUtilMajor == 56 && swResampleMajor == 3) {
+ final int swScaleMajor = swScale.version.getMajor();
+ if( avCodecMajor == 58 && avFormatMajor == 58 && ( avDeviceMajor == 58 || avDeviceMajor == 0 ) && avUtilMajor == 56 &&
+ swResampleMajor == 3 && ( swScaleMajor == 5 || swScaleMajor == 0 ) )
+ {
// Exact match: ffmpeg 4.x.y
natives = new FFMPEGv0400Natives();
- } else if( avCodecMajor == 59 && avFormatMajor == 59 && ( avDeviceMajor == 59 || avDeviceMajor == 0 ) && avUtilMajor == 57 && swResampleMajor == 4) {
+ } else if( avCodecMajor == 59 && avFormatMajor == 59 && ( avDeviceMajor == 59 || avDeviceMajor == 0 ) && avUtilMajor == 57 &&
+ swResampleMajor == 4 && ( swScaleMajor == 6 || swScaleMajor == 0 ) )
+ {
// Exact match: ffmpeg 5.x.y
natives = new FFMPEGv0500Natives();
- } else if( avCodecMajor == 60 && avFormatMajor == 60 && ( avDeviceMajor == 60 || avDeviceMajor == 0 ) && avUtilMajor == 58 && swResampleMajor == 4) {
+ } else if( avCodecMajor == 60 && avFormatMajor == 60 && ( avDeviceMajor == 60 || avDeviceMajor == 0 ) && avUtilMajor == 58 &&
+ swResampleMajor == 4 && ( swScaleMajor == 7 || swScaleMajor == 0 ) )
+ {
// Exact match: ffmpeg 6.x.y
natives = new FFMPEGv0600Natives();
} else {
@@ -351,6 +378,7 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
static boolean libsLoaded() { return libsCFUSLoaded; }
static boolean avDeviceLoaded() { return libLoaded[LIB_IDX_DEV]; }
static boolean swResampleLoaded() { return libLoaded[LIB_IDX_SWR]; }
+ static boolean swScaleLoaded() { return libLoaded[LIB_IDX_SWS]; }
static FFMPEGNatives getNatives() { return natives; }
static boolean initSingleton() { return ready; }
@@ -390,7 +418,7 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
public final List<List<String>> getToolLibNames() {
final List<List<String>> libsList = new ArrayList<List<String>>();
- // 5: util, format, codec, device, swresample
+ // 6: util, format, codec, device, swresample, swscale
final List<String> avutil = new ArrayList<String>();
if( FFMPEGMediaPlayer.PREFER_SYSTEM_LIBS ) {
@@ -490,12 +518,31 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
}
libsList.add(swresample);
+ final List<String> swscale = new ArrayList<String>();
+ if( FFMPEGMediaPlayer.PREFER_SYSTEM_LIBS ) {
+ swscale.add("swscale"); // system default
+ } else {
+ swscale.add("internal_swscale");// internal
+ }
+ swscale.add("libswscale.so.7"); // ffmpeg 6.[0-x]
+ swscale.add("libswscale.so.6"); // ffmpeg 5.[0-x]
+ swscale.add("libswscale.so.5"); // ffmpeg 4.[0-x] (Debian-11)
+
+ swscale.add("swscale-7"); // ffmpeg 6.[0-x]
+ swscale.add("swscale-6"); // ffmpeg 5.[0-x]
+ swscale.add("swscale-5"); // ffmpeg 4.[0-x]
+ if( FFMPEGMediaPlayer.PREFER_SYSTEM_LIBS ) {
+ swscale.add("internal_swscale");// internal
+ } else {
+ swscale.add("swscale"); // system default
+ }
+ libsList.add(swscale);
return libsList;
}
@Override
public List<String> getSymbolForToolLibPath() {
- // 5: util, format, codec, device, swresample
- return Arrays.asList("av_free", "av_read_frame", "avcodec_close", "avdevice_register_all", "swr_convert");
+ // 6: util, format, codec, device, swresample, swscale
+ return Arrays.asList("av_free", "av_read_frame", "avcodec_close", "avdevice_register_all", "swr_convert", "swscale_version");
}
@Override
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java
index e6784273e..974bdc10b 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java
@@ -30,7 +30,6 @@ package jogamp.opengl.util.av.impl;
import java.io.IOException;
import java.io.PrintStream;
-import java.nio.ByteBuffer;
import java.security.PrivilegedAction;
import com.jogamp.opengl.GL;
@@ -41,21 +40,19 @@ import com.jogamp.common.av.AudioFormat;
import com.jogamp.common.av.AudioSink;
import com.jogamp.common.av.AudioSinkFactory;
import com.jogamp.common.av.TimeFrameI;
-import com.jogamp.common.os.Clock;
import com.jogamp.common.util.IOUtil;
import com.jogamp.common.util.PropertyAccess;
import com.jogamp.common.util.SecurityUtil;
import com.jogamp.gluegen.runtime.ProcAddressTable;
import com.jogamp.opengl.util.GLPixelStorageModes;
-import com.jogamp.opengl.util.av.ASSEventLine;
import com.jogamp.opengl.util.av.GLMediaPlayer;
+import com.jogamp.opengl.util.av.VideoPixelFormat;
import com.jogamp.opengl.util.texture.Texture;
import jogamp.common.os.PlatformPropsImpl;
import jogamp.opengl.GLContextImpl;
import jogamp.opengl.util.av.AudioSampleFormat;
import jogamp.opengl.util.av.GLMediaPlayerImpl;
-import jogamp.opengl.util.av.VideoPixelFormat;
import jogamp.opengl.util.av.impl.FFMPEGDynamicLibraryBundleInfo.VersionedLib;
/***
@@ -98,6 +95,7 @@ import jogamp.opengl.util.av.impl.FFMPEGDynamicLibraryBundleInfo.VersionedLib;
* <li>avutil</li>
* <li>avdevice (optional for video input devices)</li>
* <li>swresample</li>
+ * <li>swscale (optional for bitmap'ed subtitles)</li>
* </ul>
* </p>
*
@@ -105,10 +103,10 @@ import jogamp.opengl.util.av.impl.FFMPEGDynamicLibraryBundleInfo.VersionedLib;
* <p>
* Currently we are binary compatible with the following major versions:
* <table border="1">
- * <tr><th>ffmpeg</th><th>avcodec</th><th>avformat</th><th>avdevice</th><th>avutil</th><th>swresample</th> <th>FFMPEG* class</th></tr>
- * <tr><td>4</td> <td>58</td> <td>58</td> <td>58</td> <td>56</td> <td>03</td> <td>FFMPEGv0400</td></tr>
- * <tr><td>5</td> <td>59</td> <td>59</td> <td>59</td> <td>57</td> <td>04</td> <td>FFMPEGv0500</td></tr>
- * <tr><td>6</td> <td>60</td> <td>60</td> <td>60</td> <td>58</td> <td>04</td> <td>FFMPEGv0600</td></tr>
+ * <tr><th>ffmpeg</th><th>avcodec</th><th>avformat</th><th>avdevice</th><th>avutil</th><th>swresample</th><th>swscale</th> <th>FFMPEG* class</th></tr>
+ * <tr><td>4</td> <td>58</td> <td>58</td> <td>58</td> <td>56</td> <td>03</td> <td>05</td> <td>FFMPEGv0400</td></tr>
+ * <tr><td>5</td> <td>59</td> <td>59</td> <td>59</td> <td>57</td> <td>04</td> <td>06</td> <td>FFMPEGv0500</td></tr>
+ * <tr><td>6</td> <td>60</td> <td>60</td> <td>60</td> <td>58</td> <td>04</td> <td>07</td> <td>FFMPEGv0600</td></tr>
* </table>
* </p>
* <p>
@@ -203,6 +201,7 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
private static final int avCodecMajorVersionCC;
private static final int avDeviceMajorVersionCC;
private static final int swResampleMajorVersionCC;
+ private static final int swScaleMajorVersionCC;
private static final boolean available;
static {
@@ -220,18 +219,21 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
avUtilMajorVersionCC = natives.getAvUtilMajorVersionCC0();
avDeviceMajorVersionCC = natives.getAvDeviceMajorVersionCC0();
swResampleMajorVersionCC = natives.getSwResampleMajorVersionCC0();
+ swScaleMajorVersionCC = natives.getSwScaleMajorVersionCC0();
} else {
avUtilMajorVersionCC = 0;
avFormatMajorVersionCC = 0;
avCodecMajorVersionCC = 0;
avDeviceMajorVersionCC = 0;
swResampleMajorVersionCC = 0;
+ swScaleMajorVersionCC = 0;
}
final VersionedLib avCodec = FFMPEGDynamicLibraryBundleInfo.avCodec;
final VersionedLib avFormat = FFMPEGDynamicLibraryBundleInfo.avFormat;
final VersionedLib avUtil = FFMPEGDynamicLibraryBundleInfo.avUtil;
final VersionedLib avDevice = FFMPEGDynamicLibraryBundleInfo.avDevice;
final VersionedLib swResample = FFMPEGDynamicLibraryBundleInfo.swResample;
+ final VersionedLib swScale = FFMPEGDynamicLibraryBundleInfo.swScale;
// final boolean avDeviceLoaded = FFMPEGDynamicLibraryBundleInfo.avDeviceLoaded();
// final boolean swResampleLoaded = FFMPEGDynamicLibraryBundleInfo.swResampleLoaded();
final int avCodecMajor = avCodec.version.getMajor();
@@ -239,11 +241,13 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
final int avUtilMajor = avUtil.version.getMajor();
final int avDeviceMajor = avDevice.version.getMajor();
final int swResampleMajor = swResample.version.getMajor();
+ final int swScaleMajor = swScale.version.getMajor();
libAVVersionGood = avCodecMajorVersionCC == avCodecMajor &&
avFormatMajorVersionCC == avFormatMajor &&
avUtilMajorVersionCC == avUtilMajor &&
( avDeviceMajorVersionCC == avDeviceMajor || 0 == avDeviceMajor ) &&
- swResampleMajorVersionCC == swResampleMajor;
+ swResampleMajorVersionCC == swResampleMajor &&
+ ( swScaleMajorVersionCC == swScaleMajor || 0 == swScaleMajor );
if( !libAVVersionGood ) {
System.err.println("FFmpeg Not Matching Compile-Time / Runtime Major-Version");
}
@@ -257,6 +261,7 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
avCodecMajorVersionCC = 0;
avDeviceMajorVersionCC = 0;
swResampleMajorVersionCC = 0;
+ swScaleMajorVersionCC = 0;
libAVVersionGood = false;
}
available = libAVGood && libAVVersionGood && null != natives;
@@ -270,6 +275,7 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
out.println("FFmpeg Util : "+FFMPEGDynamicLibraryBundleInfo.avUtil+" [cc "+avUtilMajorVersionCC+"]");
out.println("FFmpeg Device : "+FFMPEGDynamicLibraryBundleInfo.avDevice+" [cc "+avDeviceMajorVersionCC+", loaded "+FFMPEGDynamicLibraryBundleInfo.avDeviceLoaded()+"]");
out.println("FFmpeg Resample: "+FFMPEGDynamicLibraryBundleInfo.swResample+" [cc "+swResampleMajorVersionCC+", loaded "+FFMPEGDynamicLibraryBundleInfo.swResampleLoaded()+"]");
+ out.println("FFmpeg Scale : "+FFMPEGDynamicLibraryBundleInfo.swScale+" [cc "+swScaleMajorVersionCC+", loaded "+FFMPEGDynamicLibraryBundleInfo.swScaleLoaded()+"]");
out.println("FFmpeg Class : "+(null!= natives ? natives.getClass().getSimpleName() : "n/a"));
}
@Override
@@ -447,6 +453,7 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
@Override
public Object run() {
final ProcAddressTable pt = ctx.getGLProcAddressTable();
+ final long procAddrGLTexImage2D = pt.getAddressFor("glTexImage2D");
final long procAddrGLTexSubImage2D = pt.getAddressFor("glTexSubImage2D");
final long procAddrGLGetError = pt.getAddressFor("glGetError");
final long procAddrGLFlush = pt.getAddressFor("glFlush");
@@ -458,7 +465,9 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
procAddrGLEnable = 0;
}
final long procAddrGLBindTexture = pt.getAddressFor("glBindTexture");
- natives.setGLFuncs0(moviePtr, procAddrGLTexSubImage2D, procAddrGLGetError, procAddrGLFlush, procAddrGLFinish, procAddrGLEnable, procAddrGLBindTexture);
+ natives.setGLFuncs0(moviePtr, procAddrGLTexImage2D, procAddrGLTexSubImage2D,
+ procAddrGLGetError, procAddrGLFlush, procAddrGLFinish,
+ procAddrGLEnable, procAddrGLBindTexture, gl.isNPOTTextureAvailable());
return null;
} } );
audioQueueSize = AudioSink.DefaultQueueSizeWithVideo;
@@ -983,7 +992,7 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
}
@Override
- protected final int getNextTextureImpl(final GL gl, final TextureFrame nextFrame) {
+ protected final int getNextTextureImpl(final GL gl, final TextureFrame vFrame, final Texture sTex, final boolean[] sTexUsed) {
if(0==moviePtr) {
throw new GLException("FFMPEG native instance null");
}
@@ -994,15 +1003,32 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
// final Texture tex = nextFrame.getTexture();
// tex.enable(gl);
// tex.bind(gl);
- vTexID = nextFrame.getTexture().getTextureObject();
+ vTexID = vFrame.getTexture().getTextureObject();
}
/** Try decode up to 10 packets to find one containing video. */
for(int i=0; TimeFrameI.INVALID_PTS == vPTS && 10 > i; i++) {
- vPTS = natives.readNextPacket0(moviePtr, getTextureTarget(), vTexID, getTextureFormat(), getTextureType(), GL.GL_TEXTURE_2D, 0);
+ int sTexID = 0; // invalid
+ int sTexWidth = 0;
+ int sTexHeight = 0;
+ if( null != gl && !sTexUsed[0] ) {
+ // glEnable() and glBindTexture() are performed in native readNextPacket0()
+ // final Texture tex = nextFrame.getTexture();
+ // tex.enable(gl);
+ // tex.bind(gl);
+ vTexID = vFrame.getTexture().getTextureObject();
+ if( null != sTex ) {
+ sTexID = sTex.getTextureObject();
+ // FIXME: Disabled in native code, buggy on AMD GPU corrupting texture content
+ sTexWidth = sTex.getWidth();
+ sTexHeight = sTex.getHeight();
+ }
+ }
+ vPTS = natives.readNextPacket0(moviePtr, getTextureTarget(), vTexID, getTextureFormat(), getTextureType(),
+ GL.GL_TEXTURE_2D, sTexID, sTexWidth, sTexHeight, sTex, sTexUsed);
}
- if( null != nextFrame ) {
- nextFrame.setPTS(vPTS);
+ if( null != vFrame ) {
+ vFrame.setPTS(vPTS);
}
return vPTS;
}
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java
index c28028bde..2fe78cbc6 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java
@@ -1,5 +1,5 @@
/**
- * Copyright 2013-2023 JogAmp Community. All rights reserved.
+ * Copyright 2013-2024 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:
@@ -28,6 +28,7 @@
package jogamp.opengl.util.av.impl;
import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
+import jogamp.opengl.util.av.GLMediaPlayerImpl;
/* pp */ abstract class FFMPEGNatives {
@@ -42,6 +43,7 @@ import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
abstract int getAvCodecMajorVersionCC0();
abstract int getAvDeviceMajorVersionCC0();
abstract int getSwResampleMajorVersionCC0();
+ abstract int getSwScaleMajorVersionCC0();
abstract long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose);
abstract void destroyInstance0(long moviePtr);
@@ -67,8 +69,8 @@ import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
int aid, int aMaxChannelCount, int aPrefSampleRate,
int sid);
- abstract void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish,
- long procAddrGLEnable, long procAddrGLBindTexture);
+ abstract void setGLFuncs0(long moviePtr, long procAddrGLTexImage2D, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush,
+ long procAddrGLFinish, long procAddrGLEnable, long procAddrGLBindTexture, boolean hasNPOT);
abstract int getVideoPTS0(long moviePtr);
@@ -89,9 +91,13 @@ import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
* @param vTexType video texture data type
* @param sTexTarget subtitle texture target
* @param sTexID subtitle texture ID/name
+ * @param sTexWidthPre current texture size, may be increased and notified via {@link GLMediaPlayerImpl#pushSubtitleTex(Object, int, int, int, int, int, int, int, int, int)}
+ * @param sTexHeightPre current texture size, may be increased and notified via {@link GLMediaPlayerImpl#pushSubtitleTex(Object, int, int, int, int, int, int, int, int, int)}
+ * @param sTexObj subtitle texture Object to be passed to caller
+ * @param sTexUsed result value, if {@code sTexObj} is being used {@code true} must be written into it
* @return resulting current video PTS, or {@link TextureFrame#INVALID_PTS}
*/
- abstract int readNextPacket0(long moviePtr, int vTexTarget, int vTexID, int vTexFmt, int vTexType, int sTexTarget, int sTexID);
+ abstract int readNextPacket0(long moviePtr, int vTexTarget, int vTexID, int vTexFmt, int vTexType, int sTexTarget, int sTexID, int sTexWidthPre, int sTexHeightPre, Object sTexObj, boolean[] sTexUsed);
abstract int play0(long moviePtr);
abstract int pause0(long moviePtr);
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGStaticNatives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGStaticNatives.java
index 65a7e3618..854de7ad7 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGStaticNatives.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGStaticNatives.java
@@ -1,5 +1,5 @@
/**
- * Copyright 2013 JogAmp Community. All rights reserved.
+ * Copyright 2013-2024 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:
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv0400Natives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv0400Natives.java
index 8a567fa94..a7e6de270 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv0400Natives.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv0400Natives.java
@@ -1,5 +1,5 @@
/**
- * Copyright 2015-2023 JogAmp Community. All rights reserved.
+ * Copyright 2015-2024 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:
@@ -47,6 +47,9 @@ class FFMPEGv0400Natives extends FFMPEGNatives {
native int getSwResampleMajorVersionCC0();
@Override
+ native int getSwScaleMajorVersionCC0();
+
+ @Override
native long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose);
@Override
@@ -56,7 +59,7 @@ class FFMPEGv0400Natives extends FFMPEGNatives {
native void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, String sizes, int vWidth, int vHeight, int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate, int sid);
@Override
- native void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish, long procAddrGLEnable, long procAddrGLBindTexture);
+ native void setGLFuncs0(long moviePtr, long procAddrGLTexImage2D, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish, long procAddrGLEnable, long procAddrGLBindTexture, boolean hasNPOT);
@Override
native int getVideoPTS0(long moviePtr);
@@ -65,7 +68,7 @@ class FFMPEGv0400Natives extends FFMPEGNatives {
native int getAudioPTS0(long moviePtr);
@Override
- native int readNextPacket0(long moviePtr, int vTexTarget, int vTexID, int vTexFmt, int vTexType, int sTexTarget, int sTexID);
+ native int readNextPacket0(long moviePtr, int vTexTarget, int vTexID, int vTexFmt, int vTexType, int sTexTarget, int sTexID, int sTexWidthPre, int sTexHeightPre, Object sTexObj, boolean[] sTexUsed);
@Override
native int play0(long moviePtr);
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv0500Natives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv0500Natives.java
index 09ae6b7b7..7268b0627 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv0500Natives.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv0500Natives.java
@@ -1,5 +1,5 @@
/**
- * Copyright 2015-2023 JogAmp Community. All rights reserved.
+ * Copyright 2015-2024 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:
@@ -47,6 +47,9 @@ class FFMPEGv0500Natives extends FFMPEGNatives {
native int getSwResampleMajorVersionCC0();
@Override
+ native int getSwScaleMajorVersionCC0();
+
+ @Override
native long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose);
@Override
@@ -56,7 +59,7 @@ class FFMPEGv0500Natives extends FFMPEGNatives {
native void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, String sizes, int vWidth, int vHeight, int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate, int sid);
@Override
- native void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish, long procAddrGLEnable, long procAddrGLBindTexture);
+ native void setGLFuncs0(long moviePtr, long procAddrGLTexImage2D, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish, long procAddrGLEnable, long procAddrGLBindTexture, boolean hasNPOT);
@Override
native int getVideoPTS0(long moviePtr);
@@ -65,7 +68,7 @@ class FFMPEGv0500Natives extends FFMPEGNatives {
native int getAudioPTS0(long moviePtr);
@Override
- native int readNextPacket0(long moviePtr, int vTexTarget, int vTexID, int vTexFmt, int vTexType, int sTexTarget, int sTexID);
+ native int readNextPacket0(long moviePtr, int vTexTarget, int vTexID, int vTexFmt, int vTexType, int sTexTarget, int sTexID, int sTexWidthPre, int sTexHeightPre, Object sTexObj, boolean[] sTexUsed);
@Override
native int play0(long moviePtr);
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv0600Natives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv0600Natives.java
index 663e9cbd0..a87c98dbc 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv0600Natives.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv0600Natives.java
@@ -1,5 +1,5 @@
/**
- * Copyright 2015-2023 JogAmp Community. All rights reserved.
+ * Copyright 2015-2024 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:
@@ -47,6 +47,9 @@ class FFMPEGv0600Natives extends FFMPEGNatives {
native int getSwResampleMajorVersionCC0();
@Override
+ native int getSwScaleMajorVersionCC0();
+
+ @Override
native long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose);
@Override
@@ -56,7 +59,7 @@ class FFMPEGv0600Natives extends FFMPEGNatives {
native void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, String sizes, int vWidth, int vHeight, int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate, int sid);
@Override
- native void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish, long procAddrGLEnable, long procAddrGLBindTexture);
+ native void setGLFuncs0(long moviePtr, long procAddrGLTexImage2D, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish, long procAddrGLEnable, long procAddrGLBindTexture, boolean hasNPOT);
@Override
native int getVideoPTS0(long moviePtr);
@@ -65,7 +68,7 @@ class FFMPEGv0600Natives extends FFMPEGNatives {
native int getAudioPTS0(long moviePtr);
@Override
- native int readNextPacket0(long moviePtr, int vTexTarget, int vTexID, int vTexFmt, int vTexType, int sTexTarget, int sTexID);
+ native int readNextPacket0(long moviePtr, int vTexTarget, int vTexID, int vTexFmt, int vTexType, int sTexTarget, int sTexID, int sTexWidthPre, int sTexHeightPre, Object sTexObj, boolean[] sTexUsed);
@Override
native int play0(long moviePtr);
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java b/src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java
index 24b1ad4a9..f9786a5ab 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java
@@ -1,5 +1,5 @@
/**
- * Copyright 2012 JogAmp Community. All rights reserved.
+ * Copyright 2012-2024 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:
@@ -38,6 +38,7 @@ import com.jogamp.opengl.GLException;
import com.jogamp.opengl.egl.EGL;
import com.jogamp.opengl.util.av.GLMediaPlayer.State;
+import com.jogamp.opengl.util.texture.Texture;
import com.jogamp.opengl.util.texture.TextureSequence;
import jogamp.opengl.util.av.EGLMediaPlayerImpl;
@@ -105,7 +106,7 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl {
}
@Override
- protected void initStreamImpl(final int vid, final int aid, int sid) throws IOException {
+ protected void initStreamImpl(final int vid, final int aid, final int sid) throws IOException {
if(0==moviePtr) {
throw new GLException("OMX native instance null");
}
@@ -192,7 +193,7 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl {
}
@Override
- protected int getNextTextureImpl(final GL gl, final TextureFrame nextFrame) {
+ protected int getNextTextureImpl(final GL gl, final TextureFrame vFrame, final Texture sTex, final boolean[] sTexUsed) {
if(0==moviePtr) {
throw new GLException("OMX native instance null");
}