From 9bf746d7c8d1e4a3b0c363b54fe9e7a96578228a Mon Sep 17 00:00:00 2001
From: Sven Göthel <sgothel@jausoft.com>
Date: Mon, 5 Feb 2024 20:56:16 +0100
Subject: Bug 1492: GLMediaPlayer: Add playStream(..) variant passing desired
 audio- and subtitle language

---
 .../android/av/AndroidGLMediaPlayerAPI14.java      |  2 +-
 .../jogamp/opengl/util/av/GLMediaPlayerImpl.java   | 77 ++++++++++++----------
 .../jogamp/opengl/util/av/NullGLMediaPlayer.java   |  2 +-
 .../opengl/util/av/impl/FFMPEGMediaPlayer.java     |  6 +-
 .../jogamp/opengl/util/av/impl/FFMPEGNatives.java  | 11 ++--
 .../opengl/util/av/impl/FFMPEGv0400Natives.java    |  2 +-
 .../opengl/util/av/impl/FFMPEGv0500Natives.java    |  2 +-
 .../opengl/util/av/impl/FFMPEGv0600Natives.java    |  2 +-
 .../opengl/util/av/impl/OMXGLMediaPlayer.java      |  2 +-
 9 files changed, 59 insertions(+), 47 deletions(-)

(limited to 'src/jogl/classes/jogamp')

diff --git a/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java b/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java
index 0924bb67e..f046bcee2 100644
--- a/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java
+++ b/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java
@@ -281,7 +281,7 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl {
     }
 
     @Override
-    protected final void initStreamImpl(final int vid, final int aid, final int sid) throws IOException {
+    protected final void initStreamImpl(final int vid, String alang, final int aid, String slang, final int sid) throws IOException {
         if( null == getUri() ) {
             return;
         }
diff --git a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java
index 8d45edb87..776a54406 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java
@@ -141,57 +141,57 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
     private volatile float playSpeed = 1.0f;
     private float audioVolume = 1.0f;
 
-    /** Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+    /** Shall be set by the {@link #initStreamImpl(int, String, int, String, int)} method implementation. */
     private String title = "undef";
-    /** Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+    /** Shall be set by the {@link #initStreamImpl(int, String, int, String, int)} method implementation. */
     private int[] v_streams = new int[0];
-    /** Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+    /** Shall be set by the {@link #initStreamImpl(int, String, int, String, int)} method implementation. */
     private String[] v_langs = new String[0];
-    /** Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+    /** Shall be set by the {@link #initStreamImpl(int, String, int, String, int)} method implementation. */
     private int vid = GLMediaPlayer.STREAM_ID_NONE;
-    /** Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+    /** Shall be set by the {@link #initStreamImpl(int, String, int, String, int)} method implementation. */
     private int[] a_streams = new int[0];
-    /** Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+    /** Shall be set by the {@link #initStreamImpl(int, String, int, String, int)} method implementation. */
     private String[] a_langs = new String[0];
-    /** Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+    /** Shall be set by the {@link #initStreamImpl(int, String, int, String, int)} method implementation. */
     private int aid = GLMediaPlayer.STREAM_ID_NONE;
-    /** Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+    /** Shall be set by the {@link #initStreamImpl(int, String, int, String, int)} method implementation. */
     private int[] s_streams = new int[0];
-    /** Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+    /** Shall be set by the {@link #initStreamImpl(int, String, int, String, int)} method implementation. */
     private String[] s_langs = new String[0];
-    /** Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+    /** Shall be set by the {@link #initStreamImpl(int, String, int, String, int)} method implementation. */
     private int sid = GLMediaPlayer.STREAM_ID_NONE;
-    /** Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+    /** Shall be set by the {@link #initStreamImpl(int, String, int, String, int)} method implementation. */
     private int width = 0;
-    /** Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+    /** Shall be set by the {@link #initStreamImpl(int, String, int, String, int)} method implementation. */
     private int height = 0;
-    /** Video avg. fps. Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+    /** Video avg. fps. Shall be set by the {@link #initStreamImpl(int, String, int, String, int)} method implementation. */
     private float fps = 0;
-    /** Video avg. frame duration in ms. Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+    /** Video avg. frame duration in ms. Shall be set by the {@link #initStreamImpl(int, String, int, String, int)} method implementation. */
     private float frame_duration = 0f;
-    /** Stream bps. Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+    /** Stream bps. Shall be set by the {@link #initStreamImpl(int, String, int, String, int)} method implementation. */
     private int bps_stream = 0;
-    /** Video bps. Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+    /** Video bps. Shall be set by the {@link #initStreamImpl(int, String, int, String, int)} method implementation. */
     private int bps_video = 0;
-    /** Audio bps. Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+    /** Audio bps. Shall be set by the {@link #initStreamImpl(int, String, int, String, int)} method implementation. */
     private int bps_audio = 0;
-    /** In frames. Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+    /** In frames. Shall be set by the {@link #initStreamImpl(int, String, int, String, int)} method implementation. */
     private int videoFrames = 0;
-    /** In frames. Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+    /** In frames. Shall be set by the {@link #initStreamImpl(int, String, int, String, int)} method implementation. */
     private int audioFrames = 0;
-    /** In ms. Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+    /** In ms. Shall be set by the {@link #initStreamImpl(int, String, int, String, int)} method implementation. */
     private int duration = 0;
-    /** Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+    /** Shall be set by the {@link #initStreamImpl(int, String, int, String, int)} method implementation. */
     private CodecID acodecID = CodecID.NONE;
-    /** Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+    /** Shall be set by the {@link #initStreamImpl(int, String, int, String, int)} method implementation. */
     private CodecID vcodecID = CodecID.NONE;
-    /** Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+    /** Shall be set by the {@link #initStreamImpl(int, String, int, String, int)} method implementation. */
     private CodecID scodecID = CodecID.NONE;
-    /** Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+    /** Shall be set by the {@link #initStreamImpl(int, String, int, String, int)} method implementation. */
     private String acodec = unknown;
-    /** Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+    /** Shall be set by the {@link #initStreamImpl(int, String, int, String, int)} method implementation. */
     private String vcodec = unknown;
-    /** Shall be set by the {@link #initStreamImpl(int, int, int)} method implementation. */
+    /** Shall be set by the {@link #initStreamImpl(int, String, int, String, int)} method implementation. */
     private String scodec = unknown;
 
     private volatile int decodedFrameCount = 0;
@@ -210,7 +210,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
     private static final int MAX_FRAMELESS_MS_UNTIL_EOS = 5000;
     private static final int MAX_FRAMELESS_UNTIL_EOS_DEFAULT =  MAX_FRAMELESS_MS_UNTIL_EOS / 30; // default value assuming 30fps
 
-    /** See {@link #getAudioSink()}. Set by implementation if used from within {@link #initStreamImpl(int, int, int)}! */
+    /** See {@link #getAudioSink()}. Set by implementation if used from within {@link #initStreamImpl(int, String, int, String, int)}! */
     protected AudioSink audioSink = null;
     protected boolean audioSinkPlaySpeedSet = false;
 
@@ -705,7 +705,13 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
     }
 
     @Override
-    public final void playStream(final Uri streamLoc, final int vid, final int aid, final int sid, final int reqTextureCount) throws IllegalStateException, IllegalArgumentException {
+    public void playStream(final Uri streamLoc, final int vid, final int aid, final int sid, final int textureCount) throws IllegalStateException, IllegalArgumentException {
+        playStream(streamLoc, vid, null, aid, null, sid, textureCount);
+    }
+    @Override
+    public void playStream(final Uri streamLoc, final int vid,
+                           final String alang, final int aid, final String slang, final int sid, final int reqTextureCount) throws IllegalStateException, IllegalArgumentException
+    {
         synchronized( stateLock ) {
             if(State.Uninitialized != state) {
                 throw new IllegalStateException("Instance not in state unintialized: "+this);
@@ -753,7 +759,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
                 public void run() {
                     try {
                         // StreamWorker may be used, see API-doc of StreamWorker
-                        initStreamImpl(vid, aid, sid);
+                        initStreamImpl(vid, alang, aid, slang, sid);
                     } catch (final Throwable t) {
                         streamErr = new StreamException(t.getClass().getSimpleName()+" while initializing: "+GLMediaPlayerImpl.this.toString(), t);
                         changeState(new GLMediaPlayer.EventMask(GLMediaPlayer.EventMask.Bit.Error), GLMediaPlayer.State.Uninitialized);
@@ -764,6 +770,11 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
     }
     /**
      * Implementation shall set the following set of data here
+     * @param vid video stream id, see <a href="#streamIDs">audio and video Stream IDs</a>
+     * @param alang desired audio language, pass {@code null} to use {@code aid}
+     * @param aid fallback audio stream id in case {@code alang} is {@code null}, see <a href="#streamIDs">audio and video Stream IDs</a>
+     * @param slang desired subtitle language, pass {@code null} to use {@code sid}
+     * @param sid fallback subtitle stream id in case {@code alang} is {@code null}, see <a href="#streamIDs">audio and video Stream IDs</a>
      * @see #vid
      * @see #aid
      * @see #sid
@@ -776,7 +787,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
      * @see #acodec
      * @see #vcodec
     */
-    protected abstract void initStreamImpl(int vid, int aid, int sid) throws Exception;
+    protected abstract void initStreamImpl(int vid, String alang, int aid, String slang, int sid) throws Exception;
 
     @Override
     public void switchStream(final int vid, final int aid, final int sid) throws IllegalStateException, IllegalArgumentException {
@@ -1487,7 +1498,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
      * </p>
      * <p>
      * Implementations using an {@link AudioSink} shall write it's instance to {@link #audioSink}
-     * from within their {@link #initStreamImpl(int, int, int)} implementation.
+     * from within their {@link #initStreamImpl(int, String, int, String, int)} implementation.
      * </p>
      */
     @Override
@@ -1550,7 +1561,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
     }
 
     /**
-     * After {@link GLMediaPlayerImpl#initStreamImpl(int, int, int) initStreamImpl(..)} is completed via
+     * After {@link GLMediaPlayerImpl#initStreamImpl(int, String, int, String, int) initStreamImpl(..)} is completed via
      * {@link GLMediaPlayerImpl#updateAttributes(int, int, int, int, int, int, int, int, int, float, int, int, int, String, String) updateAttributes(..)},
      * the latter decides whether StreamWorker is being used.
      */
@@ -1873,7 +1884,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
     }
 
     /**
-     * Called initially by {@link #initStreamImpl(int, int, int)}, which
+     * Called initially by {@link #initStreamImpl(int, String, int, String, int)}, which
      * is called off-thread by {@link #playStream(Uri, int, int, int, int)}.
      * <p>
      * The latter catches an occurring exception and set the state delivers the error events.
diff --git a/src/jogl/classes/jogamp/opengl/util/av/NullGLMediaPlayer.java b/src/jogl/classes/jogamp/opengl/util/av/NullGLMediaPlayer.java
index b8394dace..d0aa8aa0c 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/NullGLMediaPlayer.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/NullGLMediaPlayer.java
@@ -145,7 +145,7 @@ public class NullGLMediaPlayer extends GLMediaPlayerImpl {
     }
 
     @Override
-    protected final void initStreamImpl(final int vid, final int aid, final int sid) throws IOException {
+    protected final void initStreamImpl(final int vid, String alang, final int aid, String slang, final int sid) throws IOException {
         texData = createTestTextureData();
         final float _fps = 24f;
         final int _duration = 10*60*1000; // msec
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 974bdc10b..f3af4d08b 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java
@@ -352,7 +352,7 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
     public static final String dev_video_linux = "/dev/video";
 
     @Override
-    protected final void initStreamImpl(final int vid, final int aid, final int sid) throws IOException {
+    protected final void initStreamImpl(final int vid, final String alang, final int aid, final String slang, final int sid) throws IOException {
         synchronized( moviePtrLock ) {
             if(0==moviePtr) {
                 throw new GLException("FFMPEG native instance null");
@@ -377,7 +377,7 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
             }
             final AudioFormat preferredAudioFormat = audioSink.getPreferredFormat();
             if(DEBUG) {
-                System.err.println("initStream: p2 aid "+aid+", preferred "+preferredAudioFormat+" on "+audioSink+", "+this);
+                System.err.println("initStream: p2 aid "+aid+"/"+alang+", preferred "+preferredAudioFormat+" on "+audioSink+", "+this);
             }
 
             final boolean isCameraInput = null != cameraPath;
@@ -422,7 +422,7 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
                 System.err.println("initStream: p3 stream "+getUri()+" -> "+streamLocS+" -> "+resStreamLocS);
                 System.err.println("initStream: p3 vid "+vid+", sizes "+sizes+", reqVideo "+rw+"x"+rh+"@"+rr+", aid "+aid+", aMaxChannelCount "+aMaxChannelCount+", aPrefSampleRate "+aPrefSampleRate);
             }
-            natives.setStream0(moviePtr, resStreamLocS, isCameraInput, vid, sizes, rw, rh, rr, aid, aMaxChannelCount, aPrefSampleRate, sid);
+            natives.setStream0(moviePtr, resStreamLocS, isCameraInput, vid, sizes, rw, rh, rr, alang, aid, aMaxChannelCount, aPrefSampleRate, slang, sid);
         }
     }
 
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 2fe78cbc6..08e77bc6e 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java
@@ -54,20 +54,21 @@ import jogamp.opengl.util.av.GLMediaPlayerImpl;
      *
      * @param moviePtr
      * @param url
-     * @param vid
+     * @param vid video stream id
      * @param sizes requested video size as string, i.e. 'hd720'. May be null to favor vWidth and vHeight.
      * @param vWidth requested video width (for camera mode)
      * @param vHeight requested video width (for camera mode)
      * @param vRate requested video framerate (for camera mode)
-     * @param aid
+     * @param alang desired audio language, pass {@code null} to use {@code aid}
+     * @param aid fallback audio stream id in case {@code alang} is {@code null}
      * @param aPrefSampleRate
+     * @param slang desired subtitle language, pass {@code null} to use {@code sid}
+     * @param sid fallback subtitle stream id in case {@code alang} is {@code null}
      * @param aPrefChannelCount
-     * @param sid subtitle id
      */
     abstract 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);
+                             String alang, int aid, int aMaxChannelCount, int aPrefSampleRate, String slang, int sid);
 
     abstract void setGLFuncs0(long moviePtr, long procAddrGLTexImage2D, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush,
                               long procAddrGLFinish, long procAddrGLEnable, long procAddrGLBindTexture, boolean hasNPOT);
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 a7e6de270..31b2cb65c 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv0400Natives.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv0400Natives.java
@@ -56,7 +56,7 @@ class FFMPEGv0400Natives extends FFMPEGNatives {
     native void destroyInstance0(long moviePtr);
 
     @Override
-    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);
+    native void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, String sizes, int vWidth, int vHeight, int vRate, String alang, int aid, int aMaxChannelCount, int aPrefSampleRate, String slang, int sid);
 
     @Override
     native void setGLFuncs0(long moviePtr, long procAddrGLTexImage2D, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish, long procAddrGLEnable, long procAddrGLBindTexture, boolean hasNPOT);
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 7268b0627..b811ccc57 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv0500Natives.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv0500Natives.java
@@ -56,7 +56,7 @@ class FFMPEGv0500Natives extends FFMPEGNatives {
     native void destroyInstance0(long moviePtr);
 
     @Override
-    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);
+    native void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, String sizes, int vWidth, int vHeight, int vRate, String alang, int aid, int aMaxChannelCount, int aPrefSampleRate, String slang, int sid);
 
     @Override
     native void setGLFuncs0(long moviePtr, long procAddrGLTexImage2D, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish, long procAddrGLEnable, long procAddrGLBindTexture, boolean hasNPOT);
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 a87c98dbc..d7451e559 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv0600Natives.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv0600Natives.java
@@ -56,7 +56,7 @@ class FFMPEGv0600Natives extends FFMPEGNatives {
     native void destroyInstance0(long moviePtr);
 
     @Override
-    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);
+    native void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, String sizes, int vWidth, int vHeight, int vRate, String alang, int aid, int aMaxChannelCount, int aPrefSampleRate, String slang, int sid);
 
     @Override
     native void setGLFuncs0(long moviePtr, long procAddrGLTexImage2D, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish, long procAddrGLEnable, long procAddrGLBindTexture, boolean hasNPOT);
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 f9786a5ab..01aedd1ef 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java
@@ -106,7 +106,7 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl {
     }
 
     @Override
-    protected void initStreamImpl(final int vid, final int aid, final int sid) throws IOException {
+    protected void initStreamImpl(final int vid, String alang, final int aid, String slang, final int sid) throws IOException {
         if(0==moviePtr) {
             throw new GLException("OMX native instance null");
         }
-- 
cgit v1.2.3