aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2013-08-25 09:12:19 +0200
committerSven Gothel <[email protected]>2013-08-25 09:12:19 +0200
commit1b4edb60e8c91621d93033b8732b2cdef0e7ebe7 (patch)
tree1f41cf8ef6d65253fa9cbc1ff1615c6be74538b5
parent469314fff8dc53658db932bab6108107780619ee (diff)
libav/ffmpeg: Prepare for lavc54.lavf54.lavu52
- Add compile-time/runtime version check, fail if major versions do not match assuming binary incompatibility - Add: 'av_find_input_format' for future video input support - Manually map '/dev/video<NUM>' to video input - not working yet. - WINDOWS: Set file to '<NUM>' - Set input format string depending on OS
-rwxr-xr-xmake/scripts/tests-x64.sh1
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java5
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java67
-rw-r--r--src/jogl/native/libav/ffmpeg_tool.h4
-rw-r--r--src/jogl/native/libav/jogamp_opengl_util_av_impl_FFMPEGMediaPlayer.c52
5 files changed, 111 insertions, 18 deletions
diff --git a/make/scripts/tests-x64.sh b/make/scripts/tests-x64.sh
index c3c67624c..7370d06aa 100755
--- a/make/scripts/tests-x64.sh
+++ b/make/scripts/tests-x64.sh
@@ -3,6 +3,7 @@
SDIR=`dirname $0`
#export LD_LIBRARY_PATH=/home/sven/libav/lib:$LD_LIBRARY_PATH
+#export LD_LIBRARY_PATH=/home/sven/libav-0.X/lib:$LD_LIBRARY_PATH
if [ -e $SDIR/../../../gluegen/make/scripts/setenv-build-jogl-x86_64.sh ] ; then
. $SDIR/../../../gluegen/make/scripts/setenv-build-jogl-x86_64.sh
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 8865d47be..b0181bd7d 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java
@@ -59,7 +59,7 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
private static final List<String> glueLibNames = new ArrayList<String>(); // none
- private static final int symbolCount = 42;
+ private static final int symbolCount = 43;
private static final String[] symbolNames = {
"avcodec_version",
"avformat_version",
@@ -98,6 +98,7 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
"avformat_close_input", // 53.17.0 (opt)
"av_close_input_file",
"av_register_all",
+ "av_find_input_format",
"avformat_open_input",
"av_dump_format",
"av_read_frame",
@@ -108,7 +109,7 @@ 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)
-/* 42 */ "av_find_stream_info",
+/* 43 */ "av_find_stream_info",
};
// alternate symbol names
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 e59a8849f..78f5954e5 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java
@@ -38,6 +38,7 @@ import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLException;
+import com.jogamp.common.os.Platform;
import com.jogamp.common.util.VersionNumber;
import com.jogamp.gluegen.runtime.ProcAddressTable;
import com.jogamp.opengl.util.TimeFrameI;
@@ -113,6 +114,9 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
private static final int AV_DEFAULT_AFRAMES = 8;
// Instance data
+ private static final int avUtilMajorVersionCC;
+ private static final int avFormatMajorVersionCC;
+ private static final int avCodecMajorVersionCC;
private static final VersionNumber avUtilVersion;
private static final VersionNumber avFormatVersion;
private static final VersionNumber avCodecVersion;
@@ -120,19 +124,33 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
static {
final boolean libAVGood = FFMPEGDynamicLibraryBundleInfo.initSingleton();
+ final boolean libAVVersionGood;
if( FFMPEGDynamicLibraryBundleInfo.libsLoaded() ) {
+ avUtilMajorVersionCC = getAvUtilMajorVersionCC0();
+ avFormatMajorVersionCC = getAvFormatMajorVersionCC0();
+ avCodecMajorVersionCC = getAvCodecMajorVersionCC0();
avUtilVersion = getAVVersion(getAvUtilVersion0());
avFormatVersion = getAVVersion(getAvFormatVersion0());
avCodecVersion = getAVVersion(getAvCodecVersion0());
- System.err.println("LIB_AV Util : "+avUtilVersion);
- System.err.println("LIB_AV Format: "+avFormatVersion);
- System.err.println("LIB_AV Codec : "+avCodecVersion);
+ 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+"]");
+ libAVVersionGood = avUtilMajorVersionCC == avUtilVersion.getMajor() &&
+ avFormatMajorVersionCC == avFormatVersion.getMajor() &&
+ avCodecMajorVersionCC == avCodecVersion.getMajor();
+ if( !libAVVersionGood ) {
+ System.err.println("LIB_AV Not Matching Compile-Time / Runtime Major-Version");
+ }
} else {
+ avUtilMajorVersionCC = 0;
+ avFormatMajorVersionCC = 0;
+ avCodecMajorVersionCC = 0;
avUtilVersion = null;
avFormatVersion = null;
avCodecVersion = null;
+ libAVVersionGood = false;
}
- available = libAVGood ? initIDs0() : false;
+ available = libAVGood && libAVVersionGood ? initIDs0() : false;
}
public static final boolean isAvailable() { return available; }
@@ -200,6 +218,9 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
}
}
+ public static final String dev_video = "/dev/video";
+ private static final int dev_video_len = dev_video.length();
+
@Override
protected final void initStreamImpl(int vid, int aid) throws IOException {
if(0==moviePtr) {
@@ -222,7 +243,38 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
}
// setStream(..) issues updateAttributes*(..), and defines avChosenAudioFormat, vid, aid, .. etc
final int snoopVideoFrameCount = 0; // 10*textureCount
- setStream0(moviePtr, streamLocS, vid, aid, snoopVideoFrameCount, preferredAudioFormat.channelCount, preferredAudioFormat.sampleRate);
+
+ final int streamLocSLen = streamLocS.length();
+ final String inFormat;
+ final String resStreamLocS;
+ if( streamLocSLen == dev_video_len + 1 && streamLocS.startsWith(dev_video) ) {
+ final int index = Integer.valueOf( streamLocS.substring(streamLocSLen-1) ).intValue();
+ switch(Platform.OS_TYPE) {
+ case ANDROID:
+ // ??
+ case FREEBSD:
+ case HPUX:
+ case LINUX:
+ case SUNOS:
+ resStreamLocS = streamLocS;
+ inFormat = "video4linux2";
+ break;
+ case WINDOWS:
+ resStreamLocS = String.valueOf(index);
+ inFormat = "vfwcap";
+ break;
+ case MACOS:
+ case OPENKODE:
+ default:
+ resStreamLocS = streamLocS;
+ inFormat = null;
+ break;
+ }
+ } else {
+ resStreamLocS = streamLocS;
+ inFormat = null;
+ }
+ setStream0(moviePtr, resStreamLocS, inFormat, vid, aid, snoopVideoFrameCount, preferredAudioFormat.channelCount, preferredAudioFormat.sampleRate);
}
@Override
@@ -530,8 +582,11 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
}
private static native int getAvUtilVersion0();
+ private static native int getAvUtilMajorVersionCC0();
private static native int getAvFormatVersion0();
+ private static native int getAvFormatMajorVersionCC0();
private static native int getAvCodecVersion0();
+ private static native int getAvCodecMajorVersionCC0();
private static native boolean initIDs0();
private native long createInstance0(boolean verbose);
private native void destroyInstance0(long moviePtr);
@@ -555,7 +610,7 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
* @param aChannelCount
* @param aSampleRate
*/
- private native void setStream0(long moviePtr, String url, 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 aChannelCount, int aSampleRate);
private native void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish);
private native int getVideoPTS0(long moviePtr);
diff --git a/src/jogl/native/libav/ffmpeg_tool.h b/src/jogl/native/libav/ffmpeg_tool.h
index d1320ac5d..783746378 100644
--- a/src/jogl/native/libav/ffmpeg_tool.h
+++ b/src/jogl/native/libav/ffmpeg_tool.h
@@ -79,8 +79,8 @@ typedef void (APIENTRYP PFNGLFINISH) (void);
/** Constant PTS marking the end of the stream, i.e. Integer.MIN_VALUE - 1 == 0x7FFFFFFF == {@value}. Sync w/ TimeFrameI.END_OF_STREAM_PTS */
#define END_OF_STREAM_PTS 0x7FFFFFFF
-/** Until 55.0.0 */
-#define AV_HAS_API_REQUEST_CHANNELS(pAV) (AV_VERSION_MAJOR(pAV->avcodecVersion) < 55)
+/** Until 55.0.0, but stopped working w/ 54 already :( */
+#define AV_HAS_API_REQUEST_CHANNELS(pAV) (AV_VERSION_MAJOR(pAV->avcodecVersion) < 54)
/** Since 55.0.0 */
#define AV_HAS_API_REFCOUNTED_FRAMES(pAV) (AV_VERSION_MAJOR(pAV->avcodecVersion) >= 55)
diff --git a/src/jogl/native/libav/jogamp_opengl_util_av_impl_FFMPEGMediaPlayer.c b/src/jogl/native/libav/jogamp_opengl_util_av_impl_FFMPEGMediaPlayer.c
index 6bbc33863..7bf936113 100644
--- a/src/jogl/native/libav/jogamp_opengl_util_av_impl_FFMPEGMediaPlayer.c
+++ b/src/jogl/native/libav/jogamp_opengl_util_av_impl_FFMPEGMediaPlayer.c
@@ -30,8 +30,13 @@
#include "JoglCommon.h"
#include "ffmpeg_tool.h"
+#include <libavutil/avutil.h>
#include <libavutil/pixdesc.h>
#include <libavutil/samplefmt.h>
+#if LIBAVUTIL_VERSION_MAJOR < 53
+ #include <libavutil/audioconvert.h>
+ // 52: #include <libavutil/channel_layout.h>
+#endif
#include <GL/gl.h>
static const char * const ClazzNameFFMPEGMediaPlayer = "jogamp/opengl/util/av/impl/FFMPEGMediaPlayer";
@@ -111,6 +116,7 @@ typedef void (APIENTRYP AVFORMAT_FREE_CONTEXT)(AVFormatContext *s); // 52.96.0
typedef void (APIENTRYP AVFORMAT_CLOSE_INPUT)(AVFormatContext **s); // 53.17.0
typedef void (APIENTRYP AV_CLOSE_INPUT_FILE)(AVFormatContext *s);
typedef void (APIENTRYP AV_REGISTER_ALL)(void);
+typedef AVInputFormat *(APIENTRYP AV_FIND_INPUT_FORMAT)(const char *short_name);
typedef int (APIENTRYP AVFORMAT_OPEN_INPUT)(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options);
typedef void (APIENTRYP AV_DUMP_FORMAT)(AVFormatContext *ic, int index, const char *url, int is_output);
typedef int (APIENTRYP AV_READ_FRAME)(AVFormatContext *s, AVPacket *pkt);
@@ -128,6 +134,7 @@ static AVFORMAT_FREE_CONTEXT sp_avformat_free_context; // 52.96.0
static AVFORMAT_CLOSE_INPUT sp_avformat_close_input; // 53.17.0
static AV_CLOSE_INPUT_FILE sp_av_close_input_file;
static AV_REGISTER_ALL sp_av_register_all;
+static AV_FIND_INPUT_FORMAT sp_av_find_input_format;
static AVFORMAT_OPEN_INPUT sp_avformat_open_input;
static AV_DUMP_FORMAT sp_av_dump_format;
static AV_READ_FRAME sp_av_read_frame;
@@ -139,9 +146,9 @@ static AVFORMAT_NETWORK_INIT sp_avformat_network_init; // 53.13.0
static AVFORMAT_NETWORK_DEINIT sp_avformat_network_deinit; // 53.13.0
static AVFORMAT_FIND_STREAM_INFO sp_avformat_find_stream_info; // 53.3.0
static AV_FIND_STREAM_INFO sp_av_find_stream_info;
-// count: 42
+// count: 43
-#define SYMBOL_COUNT 42
+#define SYMBOL_COUNT 43
JNIEXPORT jboolean JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGDynamicLibraryBundleInfo_initSymbols0
(JNIEnv *env, jclass clazz, jobject jSymbols, jint count)
@@ -196,6 +203,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGDynamicLibraryB
sp_avformat_close_input = (AVFORMAT_CLOSE_INPUT) (intptr_t) symbols[i++];
sp_av_close_input_file = (AV_CLOSE_INPUT_FILE) (intptr_t) symbols[i++];
sp_av_register_all = (AV_REGISTER_ALL) (intptr_t) symbols[i++];
+ sp_av_find_input_format = (AV_FIND_INPUT_FORMAT) (intptr_t) symbols[i++];
sp_avformat_open_input = (AVFORMAT_OPEN_INPUT) (intptr_t) symbols[i++];
sp_av_dump_format = (AV_DUMP_FORMAT) (intptr_t) symbols[i++];
sp_av_read_frame = (AV_READ_FRAME) (intptr_t) symbols[i++];
@@ -359,16 +367,28 @@ JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_getAvUt
(JNIEnv *env, jclass clazz) {
return (jint) sp_avutil_version();
}
+JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_getAvUtilMajorVersionCC0
+ (JNIEnv *env, jclass clazz) {
+ return (jint) LIBAVUTIL_VERSION_MAJOR;
+}
JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_getAvFormatVersion0
(JNIEnv *env, jclass clazz) {
return (jint) sp_avformat_version();
}
+JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_getAvFormatMajorVersionCC0
+ (JNIEnv *env, jclass clazz) {
+ return (jint) LIBAVFORMAT_VERSION_MAJOR;
+}
JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_getAvCodecVersion0
(JNIEnv *env, jclass clazz) {
return (jint) sp_avcodec_version();
}
+JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_getAvCodecMajorVersionCC0
+ (JNIEnv *env, jclass clazz) {
+ return (jint) LIBAVCODEC_VERSION_MAJOR;
+}
JNIEXPORT jboolean JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_initIDs0
(JNIEnv *env, jclass clazz)
@@ -468,7 +488,7 @@ static void initPTSStats(PTSStats *ptsStats);
static int64_t evalPTS(PTSStats *ptsStats, int64_t inPTS, int64_t inDTS);
JNIEXPORT void JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_setStream0
- (JNIEnv *env, jobject instance, jlong ptr, jstring jURL, jint vid, jint aid,
+ (JNIEnv *env, jobject instance, jlong ptr, jstring jURL, jstring jInFmtStr, jint vid, jint aid,
jint snoopVideoFrameCount, jint aChannelCount, jint aSampleRate)
{
int res, i;
@@ -483,8 +503,17 @@ JNIEXPORT void JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_setStre
pAV->pFormatCtx = sp_avformat_alloc_context();
// Open video file
+ AVInputFormat *inFmt = NULL;
+ const char *inFmtStr = NULL != jInFmtStr ? (*env)->GetStringUTFChars(env, jInFmtStr, &iscopy) : NULL;
+ if( NULL != inFmtStr ) {
+ inFmt = sp_av_find_input_format(inFmtStr);
+ if( NULL == inFmt ) {
+ fprintf(stderr, "Warning: Could not find input format '%s'\n", inFmtStr);
+ }
+ (*env)->ReleaseStringChars(env, jInFmtStr, (const jchar *)inFmtStr);
+ }
const char *urlPath = (*env)->GetStringUTFChars(env, jURL, &iscopy);
- res = sp_avformat_open_input(&pAV->pFormatCtx, urlPath, NULL, NULL);
+ res = sp_avformat_open_input(&pAV->pFormatCtx, urlPath, inFmt, NULL);
if(res != 0) {
JoglCommon_throwNewRuntimeException(env, "Couldn't open URI: %s", urlPath);
(*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath);
@@ -610,18 +639,25 @@ JNIEXPORT void JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_setStre
JoglCommon_throwNewRuntimeException(env, "Couldn't open audio codec %d, %s", pAV->pACodecCtx->codec_id, pAV->acodec);
return;
}
-
+ if (!pAV->pACodecCtx->channel_layout) {
+ pAV->pACodecCtx->channel_layout = getDefaultAudioChannelLayout(pAV->pACodecCtx->channels);
+ }
+ if (!pAV->pACodecCtx->channel_layout) {
+ JoglCommon_throwNewRuntimeException(env, "Couldn't determine channel layout of %d channels\n", pAV->pACodecCtx->channels);
+ return;
+ }
pAV->aSampleRate = pAV->pACodecCtx->sample_rate;
pAV->aChannels = pAV->pACodecCtx->channels;
pAV->aFrameSize = pAV->pACodecCtx->frame_size; // in samples per channel!
pAV->aSampleFmt = pAV->pACodecCtx->sample_fmt;
pAV->frames_audio = pAV->pAStream->nb_frames;
if( pAV->verbose ) {
- fprintf(stderr, "A channels %d, sample_rate %d, frame_size %d, frame_number %d, r_frame_rate %f, avg_frame_rate %f, nb_frames %d, \n",
- pAV->aChannels, pAV->aSampleRate, pAV->aFrameSize, pAV->pACodecCtx->frame_number,
+ fprintf(stderr, "A channels %d [l %d], sample_rate %d, frame_size %d, frame_number %d, r_frame_rate %f, avg_frame_rate %f, nb_frames %d, [req_chan_layout %d, req_chan %d] \n",
+ pAV->aChannels, pAV->pACodecCtx->channel_layout, pAV->aSampleRate, pAV->aFrameSize, pAV->pACodecCtx->frame_number,
my_av_q2f(pAV->pAStream->r_frame_rate),
my_av_q2f(pAV->pAStream->avg_frame_rate),
- pAV->pAStream->nb_frames);
+ pAV->pAStream->nb_frames,
+ pAV->pACodecCtx->request_channel_layout, pAV->pACodecCtx->request_channels);
}
if( 0 >= snoopVideoFrameCount ) {