diff options
Diffstat (limited to 'src/jogl/classes/jogamp/opengl/util')
10 files changed, 318 insertions, 97 deletions
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"); } |