diff options
author | Sven Göthel <[email protected]> | 2024-02-05 20:56:16 +0100 |
---|---|---|
committer | Sven Göthel <[email protected]> | 2024-02-05 20:56:16 +0100 |
commit | 9bf746d7c8d1e4a3b0c363b54fe9e7a96578228a (patch) | |
tree | 4742028d0a7b85038f4e4c504b31314383780b86 | |
parent | eff91a9e29fc97d7e5051d9900e79ba9d044fb3a (diff) |
Bug 1492: GLMediaPlayer: Add playStream(..) variant passing desired audio- and subtitle language
13 files changed, 190 insertions, 94 deletions
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index 4c7a18d77..092aa2b74 100644 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -378,7 +378,6 @@ function jrun() { #D_ARGS="-Djogamp.debug.NativeLibrary -Djogamp.debug.NativeLibrary.Lookup -Djogamp.debug.JNILibLoader -Djogamp.debug.AudioSink -Djogl.debug.GLMediaPlayer" #D_ARGS="-Djogamp.debug.NativeLibrary -Djogamp.debug.AudioSink" #D_ARGS="-Djogamp.debug.NativeLibrary -Djogamp.debug.AudioSink -Djoal.openal.lib=system" - #D_ARGS="-Djogl.debug.GLMediaPlayer" #D_ARGS="-Djogl.debug.GLMediaPlayer -Djogl.debug.GLSLCode" #D_ARGS="-Djogl.debug.GLMediaPlayer.StreamWorker.delay=25 -Djogl.debug.GLMediaPlayer" #D_ARGS="-Djogl.debug.GLMediaPlayer -Djogl.debug.GLMediaPlayer.AVSync -Djogl.debug.GLMediaPlayer.Native -Djogamp.debug.AudioSink" diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UIMediaGrid01.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UIMediaGrid01.java index dd841f3f9..f9949e70c 100644 --- a/src/demos/com/jogamp/opengl/demos/graph/ui/UIMediaGrid01.java +++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UIMediaGrid01.java @@ -93,6 +93,8 @@ public class UIMediaGrid01 { private static final List<String> MEDIA_SUFFIXES = Arrays.asList("mp4", "mkv", "m2v", "avi"); private static int aid = GLMediaPlayer.STREAM_ID_AUTO; private static int sid = GLMediaPlayer.STREAM_ID_NONE; + private static String alang = null; + private static String slang = null; private static int start_pos = 0; private static float videoAspectRatio = 16f/9f; private static boolean letterBox = true; @@ -121,6 +123,12 @@ public class UIMediaGrid01 { } else if(args[idx[0]].equals("-sid")) { idx[0]++; sid = MiscUtils.atoi(args[idx[0]], sid); + } else if(args[idx[0]].equals("-alang")) { + idx[0]++; + alang = args[idx[0]]; + } else if(args[idx[0]].equals("-slang")) { + idx[0]++; + slang = args[idx[0]]; } else if(args[idx[0]].equals("-start")) { idx[0]++; start_pos = MiscUtils.atoi(args[idx[0]], start_pos); @@ -150,7 +158,7 @@ public class UIMediaGrid01 { System.err.println(options); System.err.println("mediaDir "+mediaDir); System.err.println("maxMediaFiles "+maxMediaFiles); - System.err.println("aid "+aid); + System.err.println("aid "+aid+", alang "+alang+"; sid "+sid+", slang "+slang); System.err.println("texCount "+texCount); System.err.println("boxRatio "+videoAspectRatio); System.err.println("letterBox "+letterBox); @@ -400,7 +408,7 @@ public class UIMediaGrid01 { } final MediaPlayer graphMPlayer = new MediaPlayer(options.renderModes, scene, glMPlayer, medium, defRatio, letterBox, zoomSize, customCtrls); grid.addShape( graphMPlayer ); - glMPlayer.playStream(medium, GLMediaPlayer.STREAM_ID_AUTO, aid, sid, texCount); + glMPlayer.playStream(medium, GLMediaPlayer.STREAM_ID_AUTO, alang, aid, slang, sid, texCount); if( start_pos > 0 ) { glMPlayer.seek(start_pos * 1000); } 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 6eab3fd6f..dba61eda9 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java +++ b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java @@ -52,6 +52,7 @@ import com.jogamp.opengl.util.texture.TextureSequence; * </p> * <p> * Audio and video streams can be selected or muted via {@link #playStream(Uri, int, int, int, int)} + * or {@link #playStream(Uri, int, String, int, String, int, int)} * using the appropriate <a href="#streamIDs">stream id</a>'s. * </p> * <p> @@ -558,11 +559,33 @@ public interface GLMediaPlayer extends TextureSequence { * Value is ignored if video is muted. * @throws IllegalStateException if not invoked in {@link State#Uninitialized} * @throws IllegalArgumentException if arguments are invalid + * @see #playStream(Uri, int, String, int, String, int, int) * @since 2.6.0 */ public void playStream(Uri streamLoc, int vid, int aid, int sid, int textureCount) throws IllegalStateException, IllegalArgumentException; /** + * Same as {@link #playStream(Uri, int, int, int, int)}, but providing desired audio- and subtile languages to be selected. + * @param streamLoc the stream location + * @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> + * @param textureCount desired number of buffered textures to be decoded off-thread, will be validated by implementation. + * The minimum value is {@link #TEXTURE_COUNT_MIN} (single-threaded) or above to enable multi-threaded stream decoding. + * Default is {@link #TEXTURE_COUNT_DEFAULT}. + * Value is ignored if video is muted. + * @throws IllegalStateException if not invoked in {@link State#Uninitialized} + * @throws IllegalArgumentException if arguments are invalid + * @see #playStream(Uri, int, int, int, int) + * @since 2.6.0 + */ + 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; + + /** * Switches current {@link #playStream(Uri, int, int, int, int)} to given stream IDs and continues at same {@link #getVideoPTS()}. * <p> * Implementation just issues {@link #stop()}, {@link #seek(int)} and {@link #playStream(Uri, int, int, int, int)}. @@ -710,6 +733,7 @@ public interface GLMediaPlayer extends TextureSequence { * <p> * The language code is supposed to be 3-letters of `ISO 639-2 language codes`. * </p> + * @see #getLang(int) */ public String[] getVLangs(); @@ -731,6 +755,7 @@ public interface GLMediaPlayer extends TextureSequence { * <p> * The language code is supposed to be 3-letters of `ISO 639-2 language codes`. * </p> + * @see #getLang(int) */ public String[] getALangs(); @@ -752,6 +777,7 @@ public interface GLMediaPlayer extends TextureSequence { * <p> * The language code is supposed to be 3-letters of `ISO 639-2 language codes`. * </p> + * @see #getLang(int) */ public String[] getSLangs(); @@ -776,6 +802,12 @@ public interface GLMediaPlayer extends TextureSequence { * <p> * If the stream ID is not available, {@code und} is returned * </p> + * @see #getVStreams() + * @see #getAStreams() + * @see #getSStreams() + * @see #getVLangs() + * @see #getALangs() + * @see #getSLangs() */ public String getLang(int id); 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"); } diff --git a/src/jogl/native/libav/ffmpeg_impl_template.c b/src/jogl/native/libav/ffmpeg_impl_template.c index d807682b6..570a331ec 100644 --- a/src/jogl/native/libav/ffmpeg_impl_template.c +++ b/src/jogl/native/libav/ffmpeg_impl_template.c @@ -934,8 +934,8 @@ static int createOpenedAVCodecContext(JNIEnv* env, FFMPEGToolBasicAV_t *pAV, int JNIEXPORT void JNICALL FF_FUNC(setStream0) (JNIEnv *env, jobject instance, jlong ptr, jstring jURL, jboolean jIsCameraInput, jint vid, jstring jSizeS, jint vWidth, jint vHeight, jint vRate, - jint aid, jint aMaxChannelCount, jint aPrefSampleRate, - jint sid) + jstring jALang, jint aid, jint aMaxChannelCount, jint aPrefSampleRate, + jstring jSLang, jint sid) { char cameraName[256]; int res, i; @@ -1065,10 +1065,6 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0) pAV->bps_stream = pAV->pFormatCtx->bit_rate; } - if(pAV->verbose) { - fprintf(stderr, "Streams: %d, req vid %d aid %d\n", pAV->pFormatCtx->nb_streams, vid, aid); - } - // Find the first audio and video stream, or the one matching vid // FIXME: Libav Binary compatibility! JAU01 pAV->a_stream_count=0; @@ -1079,53 +1075,102 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0) pAV->v_streams[i]=AV_STREAM_ID_NONE; pAV->s_streams[i]=AV_STREAM_ID_NONE; } - for(i=0; i<pAV->pFormatCtx->nb_streams; i++) { - AVStream *st = pAV->pFormatCtx->streams[i]; + { + const char *alang = NULL != jALang ? (*env)->GetStringUTFChars(env, jALang, &iscopy) : NULL; + const char *slang = NULL != jSLang ? (*env)->GetStringUTFChars(env, jSLang, &iscopy) : NULL; + const int hasALang = NULL != alang; + const int hasSLang = NULL != slang; if(pAV->verbose) { + fprintf(stderr, "Streams: %d, req vid %d, aid %d (%s), sid %d (%s)\n", + pAV->pFormatCtx->nb_streams, vid, aid, hasALang?alang:"null", sid, hasSLang?slang:"null"); + } + int32_t s_aid1 = AV_STREAM_ID_AUTO; + int32_t s_aidL = AV_STREAM_ID_AUTO; + AVStream* pAStream1 = NULL; + AVStream* pAStreamL = NULL; + int32_t s_sid1 = AV_STREAM_ID_AUTO; + int32_t s_sidL = AV_STREAM_ID_AUTO; + AVStream* pSStream1 = NULL; + AVStream* pSStreamL = NULL; + + for(i=0; i<pAV->pFormatCtx->nb_streams; i++) { + AVStream *st = pAV->pFormatCtx->streams[i]; const char* lang0 = meta_get_language(st->metadata); const char* lang1 = NULL != lang0 ? lang0 : "n/a"; - fprintf(stderr, "Stream: %d: is-video %d, is-audio %d, is-sub %d, lang %s\n", i, - AVMEDIA_TYPE_VIDEO == st->codecpar->codec_type, AVMEDIA_TYPE_AUDIO == st->codecpar->codec_type, - AVMEDIA_TYPE_SUBTITLE == st->codecpar->codec_type, lang1); - } - if(AVMEDIA_TYPE_VIDEO == st->codecpar->codec_type) { - if( pAV->v_stream_count < MAX_STREAM_COUNT-1 ) { - pAV->v_streams[pAV->v_stream_count++] = i; - } - if(AV_STREAM_ID_AUTO==pAV->vid && (AV_STREAM_ID_AUTO==vid || vid == i) ) { - pAV->pVStream = st; - pAV->vid=i; - } - } else if(AVMEDIA_TYPE_AUDIO == st->codecpar->codec_type) { - if( pAV->a_stream_count < MAX_STREAM_COUNT-1 ) { - pAV->a_streams[pAV->a_stream_count++] = i; + if(pAV->verbose) { + fprintf(stderr, "Stream: %d: is-video %d, is-audio %d, is-sub %d, lang %s\n", i, + AVMEDIA_TYPE_VIDEO == st->codecpar->codec_type, AVMEDIA_TYPE_AUDIO == st->codecpar->codec_type, + AVMEDIA_TYPE_SUBTITLE == st->codecpar->codec_type, lang1); } - if(AV_STREAM_ID_AUTO==pAV->aid && (AV_STREAM_ID_AUTO==aid || aid == i) ) { - pAV->pAStream = st; - pAV->aid=i; + if(AVMEDIA_TYPE_VIDEO == st->codecpar->codec_type) { + if( pAV->v_stream_count < MAX_STREAM_COUNT-1 ) { + pAV->v_streams[pAV->v_stream_count++] = i; + if( AV_STREAM_ID_AUTO==pAV->vid && ( AV_STREAM_ID_AUTO==vid || vid == i ) ) { + pAV->pVStream = st; + pAV->vid=i; + } + } + } else if(AVMEDIA_TYPE_AUDIO == st->codecpar->codec_type) { + if( pAV->a_stream_count < MAX_STREAM_COUNT-1 ) { + pAV->a_streams[pAV->a_stream_count++] = i; + if( AV_STREAM_ID_AUTO==s_aidL && AV_STREAM_ID_AUTO==aid && NULL != lang0 && hasALang && 0==strcmp(alang, lang0) ) { + pAStreamL = st; + s_aidL = i; + } + if( AV_STREAM_ID_AUTO==s_aid1 && ( AV_STREAM_ID_AUTO==aid || aid == i ) ) { + pAStream1 = st; + s_aid1 = i; + } + } + } else if(AVMEDIA_TYPE_SUBTITLE == st->codecpar->codec_type) { + if( pAV->s_stream_count < MAX_STREAM_COUNT-1 ) { + pAV->s_streams[pAV->s_stream_count++] = i; + if( AV_STREAM_ID_AUTO==s_sidL && AV_STREAM_ID_AUTO==sid && NULL != lang0 && hasSLang && 0==strcmp(slang, lang0) ) { + pSStreamL = st; + s_sidL = i; + } + if( AV_STREAM_ID_AUTO==s_sid1 && ( AV_STREAM_ID_AUTO==sid || sid == i ) ) { + pSStream1 = st; + s_sid1 = i; + } + } } - } else if(AVMEDIA_TYPE_SUBTITLE == st->codecpar->codec_type) { - if( pAV->s_stream_count < MAX_STREAM_COUNT-1 ) { - pAV->s_streams[pAV->s_stream_count++] = i; + } + if( AV_STREAM_ID_AUTO == pAV->vid ) { + pAV->vid = AV_STREAM_ID_NONE; + } + if( AV_STREAM_ID_AUTO == pAV->aid ) { + if( AV_STREAM_ID_AUTO != s_aidL ) { + pAV->pAStream = pAStreamL; + pAV->aid = s_aidL; + } else if( AV_STREAM_ID_AUTO != s_aid1 ) { + pAV->pAStream = pAStream1; + pAV->aid = s_aid1; + } else { + pAV->aid = AV_STREAM_ID_NONE; } - if(AV_STREAM_ID_AUTO==pAV->sid && (AV_STREAM_ID_AUTO==sid || sid == i) ) { - pAV->pSStream = st; - pAV->sid=i; + } + if( AV_STREAM_ID_AUTO == pAV->sid ) { + if( AV_STREAM_ID_AUTO != s_sidL ) { + pAV->pSStream = pSStreamL; + pAV->sid = s_sidL; + } else if( AV_STREAM_ID_AUTO != s_sid1 ) { + pAV->pSStream = pSStream1; + pAV->sid = s_sid1; + } else { + pAV->sid = AV_STREAM_ID_NONE; } } - } - if( AV_STREAM_ID_AUTO == pAV->aid ) { - pAV->aid = AV_STREAM_ID_NONE; - } - if( AV_STREAM_ID_AUTO == pAV->vid ) { - pAV->vid = AV_STREAM_ID_NONE; - } - if( AV_STREAM_ID_AUTO == pAV->sid ) { - pAV->sid = AV_STREAM_ID_NONE; - } - if( pAV->verbose ) { - fprintf(stderr, "Found vid %d, aid %d, sid %d\n", pAV->vid, pAV->aid, pAV->sid); + if( pAV->verbose ) { + fprintf(stderr, "Found vid %d, aid %d, sid %d\n", pAV->vid, pAV->aid, pAV->sid); + } + if( hasALang ) { + (*env)->ReleaseStringUTFChars(env, jALang, (const char *)alang); + } + if( hasSLang ) { + (*env)->ReleaseStringUTFChars(env, jSLang, (const char *)slang); + } } if(0<=pAV->aid) { |