diff options
author | Sven Gothel <[email protected]> | 2013-08-25 09:12:19 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2013-08-25 09:12:19 +0200 |
commit | 1b4edb60e8c91621d93033b8732b2cdef0e7ebe7 (patch) | |
tree | 1f41cf8ef6d65253fa9cbc1ff1615c6be74538b5 | |
parent | 469314fff8dc53658db932bab6108107780619ee (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
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 ) { |