From 68b2dad19bd6d84f18b22f967ce320b448e8a270 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sat, 30 Dec 2023 21:18:16 +0100 Subject: GLMediaPlayer/FFMPEGMediaPlayer: Add chapter metadata support and use com.jogamp.common.av.PTS.millisToTimeStr(..) Chapter metadata is now supported via our FFMPEGMediaPlayer implementation. Added public method: 'Chapters[] GLMediaPlayer.getChapters()' --- .../com/jogamp/opengl/util/av/GLMediaPlayer.java | 28 ++++++++++++++++++---- .../jogamp/opengl/util/av/GLMediaPlayerImpl.java | 11 +++++++-- .../av/impl/FFMPEGDynamicLibraryBundleInfo.java | 12 ++++++---- .../opengl/util/av/impl/FFMPEGMediaPlayer.java | 17 +++++++++++-- .../jogamp/opengl/util/av/impl/FFMPEGNatives.java | 6 +++++ .../opengl/util/av/impl/FFMPEGv0400Natives.java | 11 +++++++++ .../opengl/util/av/impl/FFMPEGv0500Natives.java | 11 +++++++++ .../opengl/util/av/impl/FFMPEGv0600Natives.java | 11 +++++++++ 8 files changed, 94 insertions(+), 13 deletions(-) (limited to 'src/jogl/classes') diff --git a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java index 7be088c3b..e5351af03 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java +++ b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java @@ -36,12 +36,10 @@ import jogamp.opengl.Debug; import java.io.PrintStream; import java.util.List; -import com.jogamp.common.av.AudioFormat; import com.jogamp.common.av.AudioSink; import com.jogamp.common.av.PTS; import com.jogamp.common.av.TimeFrameI; import com.jogamp.common.net.Uri; -import com.jogamp.common.os.Clock; import com.jogamp.opengl.util.texture.Texture; import com.jogamp.opengl.util.texture.TextureSequence; @@ -273,6 +271,25 @@ public interface GLMediaPlayer extends TextureSequence { } } + /** Chapter meta-data of stream, see {@link GLMediaPlayer#getChapters()}. */ + public static class Chapter { + /** Chapter ID */ + public final int id; + /** Chapter start PTS in ms */ + public final int start; + /** Chapter end PTS in ms */ + public final int end; + /** Chapter title */ + public final String title; + public Chapter(final int i, final int s, final int e, final String t) { + id = i; start = s; end = e; title = t; + } + @Override + public String toString() { + return String.format("%02d: [%s .. %s] %s", id, PTS.millisToTimeStr(start), PTS.millisToTimeStr(end), title); + } + } + /** * {@inheritDoc} *

@@ -770,11 +787,14 @@ public interface GLMediaPlayer extends TextureSequence { /** Returns the height of the video. */ public int getHeight(); - /** Returns a string represantation of this player, incl. state and audio/video details. */ + /** Returns {@link Chapter} meta-data from stream, available after {@link State#Initialized} is reached after issuing {@link #playStream(Uri, int, int, int)}. */ + public Chapter[] getChapters(); + + /** Returns a string representation of this player, incl. state and audio/video details. */ @Override public String toString(); - /** Returns a string represantation of this player's performance values. */ + /** Returns a string representation of this player's performance values. */ public String getPerfString(); /** Adds a {@link GLMediaEventListener} to this player. */ diff --git a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java index e493689da..e1472102c 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java +++ b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java @@ -1718,6 +1718,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { return; } if( wasUninitialized ) { + updateMetadata(); if( DEBUG ) { logout.println("XXX Initialize @ updateAttributes: "+this); } @@ -1785,15 +1786,21 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { @Override public final int getHeight() { return height; } + /** Implementation shall update metadata, e.g. {@link #getChapters()} if supported. Called after {@link State#Initialized} is reached. */ + protected void updateMetadata() {} + + @Override + public Chapter[] getChapters() { return new Chapter[0]; } + @Override public final String toString() { - final float tt = getDuration() / 1000.0f; + final String tt = PTS.millisToTimeStr(getDuration()); final String loc = ( null != streamLoc ) ? streamLoc.toString() : "" ; 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 String camPath = null != cameraPath ? ", camera: "+cameraPath : ""; - return getClass().getSimpleName()+"["+state+", vSCR "+video_scr_ms+", frames[p "+presentedFrameCount+", d "+decodedFrameCount+", t "+videoFrames+" ("+tt+" s), z "+nullFrameCount+" / "+maxNullFrameCountUntilEOS+"], "+ + 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+", <"+vcodec+">, "+width+"x"+height+", glOrient "+isInGLOrientation+", "+fps+" fps, "+frame_duration+" fdur, "+bps_video+" bps], "+ 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 9b1782993..05a0ddb64 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java +++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java @@ -52,7 +52,7 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo { private static final List glueLibNames = new ArrayList(); // none - private static final int symbolCount = 60; + private static final int symbolCount = 61; private static final String[] symbolNames = { "avutil_version", "avformat_version", @@ -91,6 +91,7 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo { "av_samples_get_buffer_size", "av_get_bytes_per_sample", // 51.4.0 "av_opt_set_int", // 51.12.0 + "av_dict_iterate", // 57.42.100 "av_dict_get", "av_dict_count", // 54.* (opt) "av_dict_set", @@ -99,7 +100,7 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo { "av_channel_layout_uninit", // >= 59 (opt) "av_channel_layout_describe", // >= 59 (opt) "av_opt_set_chlayout", // >= 59 - /* +16 = 39 */ + /* +16 = 40 */ // libavformat "avformat_alloc_context", @@ -116,11 +117,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 = 53 */ + /* +14 = 54 */ // libavdevice "avdevice_register_all", // supported in all versions (opt) - /* +1 = 54 */ + /* +1 = 55 */ // libswresample "av_opt_set_sample_fmt", // actually lavu .. but exist only w/ swresample! @@ -129,7 +130,7 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo { "swr_free", "swr_convert", "swr_get_out_samples", - /* +6 = 60 */ + /* +6 = 61 */ }; // optional symbol names @@ -138,6 +139,7 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo { "av_dict_count", // 54.* (opt) // libavutil + "av_dict_iterate", // >= 57.42.100 "av_channel_layout_default", // >= 59 (opt) "av_channel_layout_uninit", // >= 59 (opt) "av_channel_layout_describe", // >= 59 (opt) 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 8124ca6ca..f091056c2 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java +++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java @@ -43,7 +43,6 @@ import com.jogamp.common.av.TimeFrameI; import com.jogamp.common.util.IOUtil; import com.jogamp.common.util.PropertyAccess; import com.jogamp.common.util.SecurityUtil; -import com.jogamp.common.util.VersionNumber; import com.jogamp.gluegen.runtime.ProcAddressTable; import com.jogamp.opengl.util.GLPixelStorageModes; import com.jogamp.opengl.util.av.GLMediaPlayer; @@ -413,6 +412,21 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl { natives.setStream0(moviePtr, resStreamLocS, isCameraInput, vid, sizes, rw, rh, rr, aid, aMaxChannelCount, aPrefSampleRate); } + @Override + protected void updateMetadata() { + final Chapter[] chapters = new Chapter[natives.getChapterCount0(moviePtr)]; + for(int i=0; i