summaryrefslogtreecommitdiffstats
path: root/src/jogl/native
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2014-02-16 06:12:45 +0100
committerSven Gothel <[email protected]>2014-02-16 06:12:45 +0100
commite685f79ec7071e266a1bd3d3ce3e742397b5372e (patch)
tree7328960c34c3083e91ec47793993c686359e0015 /src/jogl/native
parenta6acce1be19060a6a4801582f0534e0d6887467a (diff)
Bug 927: Fix minor MT issues w/ libav/ffmpeg
Issue: [NULL @ 0x35bde60] insufficient thread locking around avcodec_open/close() Decorating said libav functions w/ mutex lock/release. Abstract impl. to either use pthread or JNI Monitor, but using the latter to reduce dependencies (ming64 windows). FFMPEGNatives is now an abstract class containing the 'static final Object mutex_avcodec_openclose'
Diffstat (limited to 'src/jogl/native')
-rw-r--r--src/jogl/native/libav/ffmpeg_impl_template.c79
-rw-r--r--src/jogl/native/libav/ffmpeg_tool.h15
2 files changed, 74 insertions, 20 deletions
diff --git a/src/jogl/native/libav/ffmpeg_impl_template.c b/src/jogl/native/libav/ffmpeg_impl_template.c
index e86b2a542..274eb37a5 100644
--- a/src/jogl/native/libav/ffmpeg_impl_template.c
+++ b/src/jogl/native/libav/ffmpeg_impl_template.c
@@ -344,6 +344,14 @@ static void _setIsGLOriented(JNIEnv *env, FFMPEGToolBasicAV_t* pAV) {
}
}
+#ifdef USE_PTHREAD_LOCKING
+ #define MY_MUTEX_LOCK(e,s) pthread_mutex_lock(&(s))
+ #define MY_MUTEX_UNLOCK(e,s) pthread_mutex_unlock(&(s))
+#else
+ #define MY_MUTEX_LOCK(e,s) (*e)->MonitorEnter(e, s)
+ #define MY_MUTEX_UNLOCK(e,s) (*e)->MonitorExit(e, s)
+#endif
+
static void freeInstance(JNIEnv *env, FFMPEGToolBasicAV_t* pAV) {
int i;
if(NULL != pAV) {
@@ -361,19 +369,23 @@ static void freeInstance(JNIEnv *env, FFMPEGToolBasicAV_t* pAV) {
pAV->aResampleBuffer = NULL;
}
- // Close the V codec
- if(NULL != pAV->pVCodecCtx) {
- sp_avcodec_close(pAV->pVCodecCtx);
- pAV->pVCodecCtx = NULL;
- }
- pAV->pVCodec=NULL;
+ MY_MUTEX_LOCK(env, pAV->mutex_avcodec_openclose);
+ {
+ // Close the V codec
+ if(NULL != pAV->pVCodecCtx) {
+ sp_avcodec_close(pAV->pVCodecCtx);
+ pAV->pVCodecCtx = NULL;
+ }
+ pAV->pVCodec=NULL;
- // Close the A codec
- if(NULL != pAV->pACodecCtx) {
- sp_avcodec_close(pAV->pACodecCtx);
- pAV->pACodecCtx = NULL;
+ // Close the A codec
+ if(NULL != pAV->pACodecCtx) {
+ sp_avcodec_close(pAV->pACodecCtx);
+ pAV->pACodecCtx = NULL;
+ }
+ pAV->pACodec=NULL;
}
- pAV->pACodec=NULL;
+ MY_MUTEX_UNLOCK(env, pAV->mutex_avcodec_openclose);
// Close the frames
if(NULL != pAV->pVFrame) {
@@ -421,6 +433,14 @@ static void freeInstance(JNIEnv *env, FFMPEGToolBasicAV_t* pAV) {
(*env)->DeleteGlobalRef(env, pAV->ffmpegMediaPlayer);
pAV->ffmpegMediaPlayer = NULL;
}
+
+ #ifdef USE_PTHREAD_LOCKING
+ pthread_mutex_unlock(&pAV->mutex_avcodec_openclose);
+ pthread_mutex_destroy(&pAV->mutex_avcodec_openclose);
+ #else
+ (*env)->DeleteGlobalRef(env, pAV->mutex_avcodec_openclose);
+ #endif
+
free(pAV);
}
}
@@ -488,8 +508,11 @@ JNIEXPORT jint JNICALL FF_FUNC(getSwResampleMajorVersionCC0)
}
JNIEXPORT jlong JNICALL FF_FUNC(createInstance0)
- (JNIEnv *env, jobject instance, jobject ffmpegMediaPlayer, jboolean verbose)
+ (JNIEnv *env, jobject instance, jobject mutex_avcodec_openclose, jobject ffmpegMediaPlayer, jboolean verbose)
{
+ #ifdef USE_PTHREAD_LOCKING
+ pthread_mutexattr_t renderLockAttr;
+ #endif
FFMPEGToolBasicAV_t * pAV = calloc(1, sizeof(FFMPEGToolBasicAV_t));
if(NULL==pAV) {
JoglCommon_throwNewRuntimeException(env, "Couldn't alloc instance");
@@ -524,6 +547,14 @@ JNIEXPORT jlong JNICALL FF_FUNC(createInstance0)
pAV->vid=AV_STREAM_ID_AUTO;
pAV->aid=AV_STREAM_ID_AUTO;
+ #ifdef USE_PTHREAD_LOCKING
+ pthread_mutexattr_init(&renderLockAttr);
+ pthread_mutexattr_settype(&renderLockAttr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&pAV->mutex_avcodec_openclose, &renderLockAttr); // recursive
+ #else
+ pAV->mutex_avcodec_openclose = (*env)->NewGlobalRef(env, mutex_avcodec_openclose);
+ #endif
+
if(pAV->verbose) {
fprintf(stderr, "Info: Use avresample %d, swresample %d, device %d, refCount %d\n",
AV_HAS_API_AVRESAMPLE(pAV), AV_HAS_API_SWRESAMPLE(pAV), HAS_FUNC(sp_avdevice_register_all), pAV->useRefCountedFrames);
@@ -824,10 +855,14 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0)
}
// Open codec
- #if LIBAVCODEC_VERSION_MAJOR >= 55
- pAV->pACodecCtx->refcounted_frames = pAV->useRefCountedFrames;
- #endif
- res = sp_avcodec_open2(pAV->pACodecCtx, pAV->pACodec, NULL);
+ MY_MUTEX_LOCK(env, pAV->mutex_avcodec_openclose);
+ {
+ #if LIBAVCODEC_VERSION_MAJOR >= 55
+ pAV->pACodecCtx->refcounted_frames = pAV->useRefCountedFrames;
+ #endif
+ res = sp_avcodec_open2(pAV->pACodecCtx, pAV->pACodec, NULL);
+ }
+ MY_MUTEX_UNLOCK(env, pAV->mutex_avcodec_openclose);
if(res<0) {
JoglCommon_throwNewRuntimeException(env, "Couldn't open audio codec %d, %s", pAV->pACodecCtx->codec_id, pAV->acodec);
return;
@@ -982,10 +1017,14 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0)
}
// Open codec
- #if LIBAVCODEC_VERSION_MAJOR >= 55
- pAV->pVCodecCtx->refcounted_frames = pAV->useRefCountedFrames;
- #endif
- res = sp_avcodec_open2(pAV->pVCodecCtx, pAV->pVCodec, NULL);
+ MY_MUTEX_LOCK(env, pAV->mutex_avcodec_openclose);
+ {
+ #if LIBAVCODEC_VERSION_MAJOR >= 55
+ pAV->pVCodecCtx->refcounted_frames = pAV->useRefCountedFrames;
+ #endif
+ res = sp_avcodec_open2(pAV->pVCodecCtx, pAV->pVCodec, NULL);
+ }
+ MY_MUTEX_UNLOCK(env, pAV->mutex_avcodec_openclose);
if(res<0) {
JoglCommon_throwNewRuntimeException(env, "Couldn't open video codec %d, %s", pAV->pVCodecCtx->codec_id, pAV->vcodec);
return;
diff --git a/src/jogl/native/libav/ffmpeg_tool.h b/src/jogl/native/libav/ffmpeg_tool.h
index 97e60afce..66c3519e6 100644
--- a/src/jogl/native/libav/ffmpeg_tool.h
+++ b/src/jogl/native/libav/ffmpeg_tool.h
@@ -64,6 +64,15 @@ typedef struct SwrContext SwrContext;
#include <stdio.h>
#include <stdlib.h>
+// We use JNI Monitor Locking, since this removes the need
+// to statically link-in pthreads on window ..
+// #define USE_PTHREAD_LOCKING 1
+//
+#ifdef USE_PTHREAD_LOCKING
+ #include <pthread.h>
+ #error PTHREAD path not tested yet
+#endif
+
#include <GL/gl.h>
typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
@@ -148,6 +157,12 @@ typedef struct {
PFNGLFLUSH procAddrGLFlush;
PFNGLFINISH procAddrGLFinish;
+ #ifdef USE_PTHREAD_LOCKING
+ pthread_mutex_t mutex_avcodec_openclose;
+ #else
+ jobject mutex_avcodec_openclose;
+ #endif
+
AVFormatContext* pFormatCtx;
int32_t vid;
AVStream* pVStream;