summaryrefslogtreecommitdiffstats
path: root/src/jogl/classes
diff options
context:
space:
mode:
Diffstat (limited to 'src/jogl/classes')
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java77
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java174
2 files changed, 171 insertions, 80 deletions
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 b0181bd7d..2f92f9bf3 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java
@@ -59,12 +59,13 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
private static final List<String> glueLibNames = new ArrayList<String>(); // none
- private static final int symbolCount = 43;
+ private static final int symbolCount = 51;
private static final String[] symbolNames = {
"avcodec_version",
"avformat_version",
-/* 3 */ "avutil_version",
-
+ "avutil_version",
+/* 4 */ "avresample_version",
+
// libavcodec
"avcodec_close",
"avcodec_string",
@@ -83,15 +84,17 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
"av_free_packet",
"avcodec_decode_audio4", // 53.25.0 (opt)
"avcodec_decode_audio3", // 52.23.0
-/* 21 */ "avcodec_decode_video2", // 52.23.0
+/* 22 */ "avcodec_decode_video2", // 52.23.0
// libavutil
"av_pix_fmt_descriptors",
"av_frame_unref", // 55.0.0 (opt)
"av_free",
"av_get_bits_per_pixel",
-/* 26 */ "av_samples_get_buffer_size",
-
+ "av_samples_get_buffer_size",
+ "av_get_bytes_per_sample", // 51.4.0
+/* 29 */ "av_opt_set_int", // 51.12.0
+
// libavformat
"avformat_alloc_context",
"avformat_free_context", // 52.96.0 (opt)
@@ -109,7 +112,14 @@ 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)
-/* 43 */ "av_find_stream_info",
+/* 46 */ "av_find_stream_info",
+
+ // libavresample
+ "avresample_alloc_context", // 1.0.1
+ "avresample_open",
+ "avresample_close",
+ "avresample_free",
+/* 51 */ "avresample_convert"
};
// alternate symbol names
@@ -128,23 +138,34 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
"avformat_seek_file", // ??? (opt)
"avcodec_free_frame", // 54.28.0 (opt)
"av_frame_unref", // 55.0.0 (opt)
+
+ // libavresample
+ "avresample_version", // 1.0.1
+ "avresample_alloc_context", // 1.0.1
+ "avresample_open",
+ "avresample_close",
+ "avresample_free",
+ "avresample_convert",
};
private static long[] symbolAddr;
private static final boolean ready;
private static final boolean libsLoaded;
+ private static final boolean avresampleLoaded; // optional
static {
// native ffmpeg media player implementation is included in jogl_desktop and jogl_mobile
GLProfile.initSingleton();
boolean _ready = false;
boolean[] _libsLoaded= { false };
+ boolean[] _avresampleLoaded= { false };
try {
- _ready = initSymbols(_libsLoaded);
+ _ready = initSymbols(_libsLoaded, _avresampleLoaded);
} catch (Throwable t) {
t.printStackTrace();
}
libsLoaded = _libsLoaded[0];
+ avresampleLoaded = _avresampleLoaded[0];
ready = _ready;
if(!libsLoaded) {
System.err.println("LIB_AV Not Available");
@@ -154,9 +175,10 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
}
static boolean libsLoaded() { return libsLoaded; }
+ static boolean avResampleLoaded() { return avresampleLoaded; }
static boolean initSingleton() { return ready; }
- private static final boolean initSymbols(boolean[] libsLoaded) {
+ private static final boolean initSymbols(boolean[] libsLoaded, boolean[] avresampleLoaded) {
libsLoaded[0] = false;
final DynamicLibraryBundle dl = AccessController.doPrivileged(new PrivilegedAction<DynamicLibraryBundle>() {
public DynamicLibraryBundle run() {
@@ -167,10 +189,12 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
final boolean avcodecLoaded = dl.isToolLibLoaded(2);
if(!avutilLoaded || !avformatLoaded || !avcodecLoaded) {
throw new RuntimeException("FFMPEG Tool library incomplete: [ avutil "+avutilLoaded+", avformat "+avformatLoaded+", avcodec "+avcodecLoaded+"]");
- }
+ }
+ avresampleLoaded[0] = dl.isToolLibLoaded(3);
+ /** Ignore .. due to optional libavresample
if(!dl.isToolLibComplete()) {
throw new RuntimeException("FFMPEG Tool libraries incomplete");
- }
+ } */
libsLoaded[0] = true;
if(symbolNames.length != symbolCount) {
throw new InternalError("XXX0 "+symbolNames.length+" != "+symbolCount);
@@ -205,6 +229,7 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
} } );
// validate results
+ boolean res = true;
for(int i = 0; i<symbolCount; i++) {
if( 0 == symbolAddr[i] ) {
// no symbol, check optional and alternative symbols
@@ -226,14 +251,14 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
}
if(!ok) {
System.err.println("Fail: Could not resolve symbol <"+symbolNames[i]+">: not optional, no alternatives.");
- return false;
+ res = false;
}
} else if(DEBUG) {
System.err.println("OK: Unresolved optional symbol <"+symbolNames[i]+">");
}
}
}
- return initSymbols0(symbolAddr, symbolCount);
+ return initSymbols0(symbolAddr, symbolCount) && res;
}
protected FFMPEGDynamicLibraryBundleInfo() {
@@ -265,11 +290,13 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
final List<String> avutil = new ArrayList<String>();
avutil.add("avutil"); // default
- avutil.add("libavutil.so.52"); // dummy future proof
+ avutil.add("libavutil.so.53"); // dummy future proof
+ avutil.add("libavutil.so.52"); // 9
avutil.add("libavutil.so.51"); // 0.8
avutil.add("libavutil.so.50"); // 0.7
- avutil.add("avutil-52"); // dummy future proof
+ avutil.add("avutil-53"); // dummy future proof
+ avutil.add("avutil-52"); // 9
avutil.add("avutil-51"); // 0.8
avutil.add("avutil-50"); // 0.7
libsList.add(avutil);
@@ -278,12 +305,12 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
avformat.add("avformat"); // default
avformat.add("libavformat.so.55"); // dummy future proof
- avformat.add("libavformat.so.54"); // 0.?
+ avformat.add("libavformat.so.54"); // 9
avformat.add("libavformat.so.53"); // 0.8
avformat.add("libavformat.so.52"); // 0.7
avformat.add("avformat-55"); // dummy future proof
- avformat.add("avformat-54"); // 0.?
+ avformat.add("avformat-54"); // 9
avformat.add("avformat-53"); // 0.8
avformat.add("avformat-52"); // 0.7
libsList.add(avformat);
@@ -292,16 +319,26 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
avcodec.add("avcodec"); // default
avcodec.add("libavcodec.so.55"); // dummy future proof
- avcodec.add("libavcodec.so.54"); // 0.?
+ avcodec.add("libavcodec.so.54"); // 9
avcodec.add("libavcodec.so.53"); // 0.8
avcodec.add("libavcodec.so.52"); // 0.7
avcodec.add("avcodec-55"); // dummy future proof
- avcodec.add("avcodec-54"); // 0.?
+ avcodec.add("avcodec-54"); // 9
avcodec.add("avcodec-53"); // 0.8
avcodec.add("avcodec-52"); // 0.7
libsList.add(avcodec);
-
+
+ final List<String> avresample = new ArrayList<String>();
+ avresample.add("avresample"); // default
+
+ avresample.add("libavresample.so.2"); // dummy future proof
+ avresample.add("libavresample.so.1"); // 9
+
+ avresample.add("avresample-2"); // dummy future proof
+ avresample.add("avresample-1"); // 9
+ libsList.add(avresample);
+
return libsList;
}
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 78f5954e5..80b946456 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java
@@ -44,8 +44,7 @@ import com.jogamp.gluegen.runtime.ProcAddressTable;
import com.jogamp.opengl.util.TimeFrameI;
import com.jogamp.opengl.util.GLPixelStorageModes;
import com.jogamp.opengl.util.av.AudioSink;
-import com.jogamp.opengl.util.av.AudioSink.AudioDataFormat;
-import com.jogamp.opengl.util.av.AudioSink.AudioDataType;
+import com.jogamp.opengl.util.av.AudioSink.AudioFormat;
import com.jogamp.opengl.util.av.AudioSinkFactory;
import com.jogamp.opengl.util.av.GLMediaPlayer;
import com.jogamp.opengl.util.texture.Texture;
@@ -117,9 +116,11 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
private static final int avUtilMajorVersionCC;
private static final int avFormatMajorVersionCC;
private static final int avCodecMajorVersionCC;
+ private static final int avResampleMajorVersionCC;
private static final VersionNumber avUtilVersion;
private static final VersionNumber avFormatVersion;
private static final VersionNumber avCodecVersion;
+ private static final VersionNumber avResampleVersion;
private static final boolean available;
static {
@@ -129,15 +130,19 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
avUtilMajorVersionCC = getAvUtilMajorVersionCC0();
avFormatMajorVersionCC = getAvFormatMajorVersionCC0();
avCodecMajorVersionCC = getAvCodecMajorVersionCC0();
+ avResampleMajorVersionCC = getAvResampleMajorVersionCC0();
avUtilVersion = getAVVersion(getAvUtilVersion0());
avFormatVersion = getAVVersion(getAvFormatVersion0());
avCodecVersion = getAVVersion(getAvCodecVersion0());
- System.err.println("LIB_AV Util : "+avUtilVersion+" [cc "+avUtilMajorVersionCC+"]");
- System.err.println("LIB_AV Format: "+avFormatVersion+" [cc "+avFormatMajorVersionCC+"]");
- System.err.println("LIB_AV Codec : "+avCodecVersion+" [cc "+avCodecMajorVersionCC+"]");
+ avResampleVersion = getAVVersion(getAvResampleVersion0());
+ System.err.println("LIB_AV Util : "+avUtilVersion+" [cc "+avUtilMajorVersionCC+"]");
+ System.err.println("LIB_AV Format : "+avFormatVersion+" [cc "+avFormatMajorVersionCC+"]");
+ System.err.println("LIB_AV Codec : "+avCodecVersion+" [cc "+avCodecMajorVersionCC+"]");
+ System.err.println("LIB_AV Resample: "+avResampleVersion+" [cc "+avResampleMajorVersionCC+"]");
libAVVersionGood = avUtilMajorVersionCC == avUtilVersion.getMajor() &&
avFormatMajorVersionCC == avFormatVersion.getMajor() &&
- avCodecMajorVersionCC == avCodecVersion.getMajor();
+ avCodecMajorVersionCC == avCodecVersion.getMajor() &&
+ avResampleMajorVersionCC == avResampleVersion.getMajor();
if( !libAVVersionGood ) {
System.err.println("LIB_AV Not Matching Compile-Time / Runtime Major-Version");
}
@@ -145,9 +150,11 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
avUtilMajorVersionCC = 0;
avFormatMajorVersionCC = 0;
avCodecMajorVersionCC = 0;
+ avResampleMajorVersionCC = 0;
avUtilVersion = null;
avFormatVersion = null;
avCodecVersion = null;
+ avResampleVersion = null;
libAVVersionGood = false;
}
available = libAVGood && libAVVersionGood ? initIDs0() : false;
@@ -185,9 +192,7 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
// Audio
//
- private SampleFormat aSampleFmt = null;
- private AudioSink.AudioDataFormat avChosenAudioFormat;
- private AudioSink.AudioDataFormat sinkChosenAudioFormat;
+ private AudioSink.AudioFormat avChosenAudioFormat;
private int audioSamplesPerFrameAndChannel = 0;
public FFMPEGMediaPlayer() {
@@ -237,7 +242,7 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
} else {
audioSink = AudioSinkFactory.createDefault();
}
- final AudioDataFormat preferredAudioFormat = audioSink.getPreferredFormat();
+ final AudioFormat preferredAudioFormat = audioSink.getPreferredFormat();
if(DEBUG) {
System.err.println("initStream: p2 preferred "+preferredAudioFormat+", "+this);
}
@@ -274,7 +279,9 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
resStreamLocS = streamLocS;
inFormat = null;
}
- setStream0(moviePtr, resStreamLocS, inFormat, vid, aid, snoopVideoFrameCount, preferredAudioFormat.channelCount, preferredAudioFormat.sampleRate);
+ final int aMaxChannelCount = audioSink.getMaxSupportedChannels();
+ final int aPrefSampleRate = preferredAudioFormat.sampleRate;
+ setStream0(moviePtr, resStreamLocS, inFormat, vid, aid, snoopVideoFrameCount, aMaxChannelCount, aPrefSampleRate);
}
@Override
@@ -308,20 +315,20 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
} else {
frameDuration = AudioSink.DefaultFrameDuration;
}
-
- sinkChosenAudioFormat = audioSink.init(avChosenAudioFormat, frameDuration, AudioSink.DefaultInitialQueueSize, AudioSink.DefaultQueueGrowAmount, audioQueueLimit);
if(DEBUG) {
- System.err.println("initGL: p3 avChosen "+avChosenAudioFormat+", chosen "+sinkChosenAudioFormat);
+ System.err.println("initGL: p3 avChosen "+avChosenAudioFormat);
}
- if( null == sinkChosenAudioFormat ) {
+
+ final boolean audioSinkOK = audioSink.init(avChosenAudioFormat, frameDuration, AudioSink.DefaultInitialQueueSize, AudioSink.DefaultQueueGrowAmount, audioQueueLimit);
+ if( !audioSinkOK ) {
System.err.println("AudioSink "+audioSink.getClass().getName()+" does not support "+avChosenAudioFormat+", using Null");
audioSink.destroy();
audioSink = AudioSinkFactory.createNull();
- sinkChosenAudioFormat = audioSink.init(avChosenAudioFormat, 0, AudioSink.DefaultInitialQueueSize, AudioSink.DefaultQueueGrowAmount, audioQueueLimit);
+ audioSink.init(avChosenAudioFormat, 0, AudioSink.DefaultInitialQueueSize, AudioSink.DefaultQueueGrowAmount, audioQueueLimit);
}
if(DEBUG) {
- System.err.println("initGL: p4 chosen "+sinkChosenAudioFormat);
- System.err.println("initGL: "+audioSink);
+ System.err.println("initGL: p4 chosen "+avChosenAudioFormat);
+ System.err.println("initGL: p4 chosen "+audioSink);
}
if( null != gl ) {
@@ -350,6 +357,84 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
}
/**
+ * @param sampleRate sample rate in Hz (1/s)
+ * @param sampleSize sample size in bits
+ * @param channelCount number of channels
+ * @param signed true if signed number, false for unsigned
+ * @param fixedP true for fixed point value, false for unsigned floating point value with a sampleSize of 32 (float) or 64 (double)
+ * @param planar true for planar data package (each channel in own data buffer), false for packed data channels interleaved in one buffer.
+ * @param littleEndian true for little-endian, false for big endian
+ * @return
+ */
+
+ /**
+ * Converts the given libav/ffmpeg values to {@link AudioFormat} and returns {@link AudioSink#isSupported(AudioFormat)}.
+ * @param audioSampleFmt ffmpeg/libav audio-sample-format, see {@link SampleFormat}.
+ * @param audioSampleRate sample rate in Hz (1/s)
+ * @param audioChannels number of channels
+ */
+ private final boolean isAudioFormatSupported(int audioSampleFmt, int audioSampleRate, int audioChannels) {
+ final AudioFormat audioFormat = avAudioFormat2Local(SampleFormat.valueOf(audioSampleFmt), audioSampleRate, audioChannels);
+ final boolean res = audioSink.isSupported(audioFormat);
+ if( DEBUG ) {
+ System.err.println("AudioSink.isSupported: "+res+": "+audioFormat);
+ }
+ return res;
+ }
+
+ /**
+ * Returns {@link AudioFormat} as converted from the given libav/ffmpeg values.
+ * @param audioSampleFmt ffmpeg/libav audio-sample-format, see {@link SampleFormat}.
+ * @param audioSampleRate sample rate in Hz (1/s)
+ * @param audioChannels number of channels
+ */
+ private final AudioFormat avAudioFormat2Local(SampleFormat audioSampleFmt, int audioSampleRate, int audioChannels) {
+ final int sampleSize;
+ boolean planar = true;
+ final boolean signed, fixedP;
+ switch( audioSampleFmt ) {
+ case S32:
+ planar = false;
+ case S32P:
+ sampleSize = 32;
+ signed = true;
+ fixedP = true;
+ break;
+ case S16:
+ planar = false;
+ case S16P:
+ sampleSize = 16;
+ signed = true;
+ fixedP = true;
+ break;
+ case U8:
+ planar = false;
+ case U8P:
+ sampleSize = 8;
+ signed = false;
+ fixedP = true;
+ break;
+ case DBL:
+ planar = false;
+ case DBLP:
+ sampleSize = 64;
+ signed = true;
+ fixedP = true;
+ break;
+ case FLT:
+ planar = false;
+ case FLTP:
+ sampleSize = 32;
+ signed = true;
+ fixedP = true;
+ break;
+ default: // FIXME: Add more formats !
+ throw new IllegalArgumentException("Unsupported sampleformat: "+audioSampleFmt);
+ }
+ return new AudioFormat(audioSampleRate, sampleSize, audioChannels, signed, fixedP, planar, true /* littleEndian */);
+ }
+
+ /**
* @param pixFmt
* @param planes
* @param bitsPerPixel
@@ -400,44 +485,9 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
default: // FIXME: Add more formats !
throw new RuntimeException("Unsupported pixelformat: "+vPixelFmt);
}
- aSampleFmt = SampleFormat.valueOf(audioSampleFmt);
- final int sampleSize;
- final boolean signed, fixedP;
- switch( aSampleFmt ) {
- case S32:
- case S32P:
- sampleSize = 32;
- signed = true;
- fixedP = true;
- break;
- case S16:
- case S16P:
- sampleSize = 16;
- signed = true;
- fixedP = true;
- break;
- case U8:
- case U8P:
- sampleSize = 8;
- signed = false;
- fixedP = true;
- break;
- case DBL:
- case DBLP:
- sampleSize = 64;
- signed = true;
- fixedP = true;
- break;
- case FLT:
- case FLTP:
- sampleSize = 32;
- signed = true;
- fixedP = true;
- break;
- default: // FIXME: Add more formats !
- throw new RuntimeException("Unsupported sampleformat: "+aSampleFmt);
- }
- avChosenAudioFormat = new AudioDataFormat(AudioDataType.PCM, audioSampleRate, sampleSize, audioChannels, signed, fixedP, true /* littleEndian */);
+ final SampleFormat aSampleFmt = SampleFormat.valueOf(audioSampleFmt);
+ avChosenAudioFormat = avAudioFormat2Local(aSampleFmt, audioSampleRate, audioChannels);
+
this.audioSamplesPerFrameAndChannel = audioSamplesPerFrameAndChannel;
if(DEBUG) {
@@ -587,6 +637,8 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
private static native int getAvFormatMajorVersionCC0();
private static native int getAvCodecVersion0();
private static native int getAvCodecMajorVersionCC0();
+ private static native int getAvResampleVersion0();
+ private static native int getAvResampleMajorVersionCC0();
private static native boolean initIDs0();
private native long createInstance0(boolean verbose);
private native void destroyInstance0(long moviePtr);
@@ -595,7 +647,7 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
* Issues {@link #updateAttributes(int, int, int, int, int, int, int, float, int, int, String, String)}
* and {@link #updateAttributes2(int, int, int, int, int, int, int, int, int, int)}.
* <p>
- * Always uses {@link AudioSink.AudioDataFormat}:
+ * Always uses {@link AudioSink.AudioFormat}:
* <pre>
* [type PCM, sampleRate [10000(?)..44100..48000], sampleSize 16, channelCount 1-2, signed, littleEndian]
* </pre>
@@ -607,10 +659,10 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
* @param aid
* @param snoopVideoFrameCount snoop this number of video-frames to gather audio-frame-count per video-frame.
* If zero, gathering audio-frame-count is disabled!
- * @param aChannelCount
- * @param aSampleRate
+ * @param aPrefChannelCount
+ * @param aPrefSampleRate
*/
- private native void setStream0(long moviePtr, String url, String inFormat, int vid, int aid, int snoopVideoFrameCount, int aChannelCount, int aSampleRate);
+ private native void setStream0(long moviePtr, String url, String inFormat, int vid, int aid, int snoopVideoFrameCount, int aMaxChannelCount, int aPrefSampleRate);
private native void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish);
private native int getVideoPTS0(long moviePtr);
@@ -627,6 +679,7 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
private native int pause0(long moviePtr);
private native int seek0(long moviePtr, int position);
+ /** FFMPEG/libAV Audio Sample Format */
public static enum SampleFormat {
// NONE = -1,
U8, ///< unsigned 8 bits
@@ -653,6 +706,7 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
}
};
+ /** FFMPEG/libAV Pixel Format */
public static enum PixelFormat {
// NONE= -1,
YUV420P, ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)