aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl/native
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2013-08-10 09:14:19 +0200
committerSven Gothel <[email protected]>2013-08-10 09:14:19 +0200
commit6332e13b2f0aa9818d37802302f04c90a4fa4239 (patch)
treeb615630b4a886270721f82636a323ec36dac341c /src/jogl/native
parent590d78dc2ff24ce80976a30e35a99c06ef6750b0 (diff)
GLMediaPlayer: Add multithreaded decoding w/ textureCount > 2 where available EGL/FFMPeg. WIP!
Off-thread decoding: If validated (impl) textureCount > 2, decoding happens on extra thread. If decoding requires GL context, a shared context is created for decoding thread. API Changes: - initGLStream(..): Adds 'textureCount' as argument. - TextureSequence.TexSeqEventListener.newFrameAvailable(..) exposes the new frame available - TextureSequence.TextureFrame exposes the PTS (video) Implementation: - 'int validateTextureCount(int)': implementation decides whether textureCount can be > 2, i.e. off-thread decoding allowed, default is NO w/ textureCount==2! - 'boolean requiresOffthreadGLCtx()': implementation decides whether shared context is required for off-thread decoding - 'syncFrame2Audio(TextureFrame frame)': implementation shall handle a/v sync, due to audio stream details (pts, buffered frames) - FFMPEGMediaPlayer extends GLMediaPlayerImpl, no more EGLMediaPlayerImpl (redundant) +++ - SyncedRingbuffer: Expose T[] array +++ TODO: - syncAV! - test Android
Diffstat (limited to 'src/jogl/native')
-rw-r--r--src/jogl/native/libav/ffmpeg_tool.h8
-rw-r--r--src/jogl/native/libav/jogamp_opengl_util_av_impl_FFMPEGMediaPlayer.c59
-rw-r--r--src/jogl/native/openmax/omx_tool.c8
3 files changed, 55 insertions, 20 deletions
diff --git a/src/jogl/native/libav/ffmpeg_tool.h b/src/jogl/native/libav/ffmpeg_tool.h
index 5560b8617..2dff1110c 100644
--- a/src/jogl/native/libav/ffmpeg_tool.h
+++ b/src/jogl/native/libav/ffmpeg_tool.h
@@ -48,6 +48,11 @@
#include <stdio.h>
#include <stdlib.h>
+#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);
+typedef GLenum (APIENTRYP PFNGLGETERRORPROC) (void);
+
/**
* AV_TIME_BASE 1000000
*/
@@ -63,6 +68,9 @@ static inline int32_t my_av_q2i32(int32_t snum, AVRational a){
typedef struct {
int32_t verbose;
+ PFNGLTEXSUBIMAGE2DPROC procAddrGLTexSubImage2D;
+ PFNGLGETERRORPROC procAddrGLGetError;
+
AVFormatContext* pFormatCtx;
int32_t vid;
AVStream* pVStream;
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 623bdcac7..346ba6c07 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
@@ -33,8 +33,6 @@
#include <libavutil/pixdesc.h>
#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);
-
static const char * const ClazzNameFFMPEGMediaPlayer = "jogamp/opengl/util/av/impl/FFMPEGMediaPlayer";
static jclass ffmpegMediaPlayerClazz = NULL;
@@ -583,22 +581,29 @@ JNIEXPORT void JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_setStre
_updateJavaAttributes(env, instance, pAV);
}
+JNIEXPORT void JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_setGLFuncs0
+ (JNIEnv *env, jobject instance, jlong ptr, jlong jProcAddrGLTexSubImage2D, jlong jProcAddrGLGetError)
+{
+ FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr));
+ pAV->procAddrGLTexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC) (intptr_t)jProcAddrGLTexSubImage2D;
+ pAV->procAddrGLGetError = (PFNGLGETERRORPROC) (intptr_t)jProcAddrGLGetError;
+}
+
JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_readNextPacket0
- (JNIEnv *env, jobject instance, jlong ptr, jlong jProcAddrGLTexSubImage2D, jint texTarget, jint texFmt, jint texType)
+ (JNIEnv *env, jobject instance, jlong ptr, jint texTarget, jint texFmt, jint texType)
{
FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr));
- PFNGLTEXSUBIMAGE2DPROC procAddrGLTexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC) (intptr_t)jProcAddrGLTexSubImage2D;
- jint res = 0; // 1 - audio, 2 - video
AVPacket packet;
int frameFinished;
+ jint resPTS = 0; // resulting current PTS: audio < 0, video > 0, invalid == 0
if(sp_av_read_frame(pAV->pFormatCtx, &packet)>=0) {
if(packet.stream_index==pAV->aid) {
// Decode audio frame
if(NULL == pAV->pAFrames) { // no audio registered
sp_av_free_packet(&packet);
- return res;
+ return 0;
}
AVFrame* pAFrameCurrent = pAV->pAFrames[pAV->aFrameCurrent];
pAV->aFrameCurrent = ( pAV->aFrameCurrent + 1 ) % pAV->aFrameCount ;
@@ -658,14 +663,13 @@ JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_readNex
jobject jSampleData = (*env)->NewDirectByteBuffer(env, pAFrameCurrent->data[0], data_size);
(*env)->CallVoidMethod(env, instance, jni_mid_pushSound, jSampleData, data_size, pAV->aPTS);
}
-
- res = 1;
+ resPTS = pAV->aPTS * -1; // Audio Frame!
}
} else if(packet.stream_index==pAV->vid) {
// Decode video frame
if(NULL == pAV->pVFrame) {
sp_av_free_packet(&packet);
- return res;
+ return 0;
}
int new_packet = 1;
@@ -696,7 +700,6 @@ JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_readNex
continue;
}
- res = 2;
// FIXME: Libav Binary compatibility! JAU01
const AVRational time_base = pAV->pVStream->time_base;
const int64_t pts = pAV->pVFrame->pkt_pts;
@@ -708,6 +711,7 @@ JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_readNex
pAV->vPTS, pAV->pVFrame->pkt_pts, time_base.num, time_base.den, (time_base.num/(double)time_base.den));
#endif
}
+ resPTS = pAV->vPTS; // Video Frame!
#if 0
printf("tex2D codec %dx%d - frame %dx%d - width %d tex / %d linesize, pixfmt 0x%X, texType 0x%x, texTarget 0x%x\n",
@@ -718,24 +722,51 @@ JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_readNex
// 1st plane or complete packed frame
// FIXME: Libav Binary compatibility! JAU01
- procAddrGLTexSubImage2D(texTarget, 0,
+ #if 0
+ GLenum glerr = pAV->procAddrGLGetError();
+ printf("TexSubImage2D.1 texTarget 0x%x, offset %d / %d, size %d x %d, fmt 0x%X, type 0x%X, pre-err 0x%X, ",
+ texTarget, 0, 0, pAV->vTexWidth[0], pAV->pVCodecCtx->height, texFmt, texType, glerr);
+ #endif
+ pAV->procAddrGLTexSubImage2D(texTarget, 0,
0, 0,
pAV->vTexWidth[0], pAV->pVCodecCtx->height,
texFmt, texType, pAV->pVFrame->data[0]);
+ #if 0
+ glerr = pAV->procAddrGLGetError();
+ printf("err 0x%X\n", glerr);
+ #endif
if(pAV->vPixFmt == PIX_FMT_YUV420P) {
// U plane
// FIXME: Libav Binary compatibility! JAU01
- procAddrGLTexSubImage2D(texTarget, 0,
+ #if 0
+ printf("TexSubImage2D.U texTarget 0x%x, offset %d / %d, size %d x %d, fmt 0x%X, type 0x%X, ",
+ texTarget, pAV->pVCodecCtx->width, 0, pAV->vTexWidth[1], pAV->pVCodecCtx->height/2,
+ texFmt, texType);
+ #endif
+ pAV->procAddrGLTexSubImage2D(texTarget, 0,
pAV->pVCodecCtx->width, 0,
pAV->vTexWidth[1], pAV->pVCodecCtx->height/2,
texFmt, texType, pAV->pVFrame->data[1]);
+ #if 0
+ glerr = pAV->procAddrGLGetError();
+ printf("err 0x%X\n", glerr);
+ #endif
// V plane
// FIXME: Libav Binary compatibility! JAU01
- procAddrGLTexSubImage2D(texTarget, 0,
+ #if 0
+ printf("TexSubImage2D.V texTarget 0x%x, offset %d / %d, size %d x %d, fmt 0x%X, type 0x%X, ",
+ texTarget, pAV->pVCodecCtx->width, pAV->pVCodecCtx->height/2, pAV->vTexWidth[2], pAV->pVCodecCtx->height/2,
+ texFmt, texType);
+ #endif
+ pAV->procAddrGLTexSubImage2D(texTarget, 0,
pAV->pVCodecCtx->width, pAV->pVCodecCtx->height/2,
pAV->vTexWidth[2], pAV->pVCodecCtx->height/2,
texFmt, texType, pAV->pVFrame->data[2]);
+ #if 0
+ glerr = pAV->procAddrGLGetError();
+ printf("err 0x%X\n", glerr);
+ #endif
} // FIXME: Add more planar formats !
}
}
@@ -745,7 +776,7 @@ JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_readNex
// TODO: check what release the packets memory.
// sp_av_free_packet(&packet);
}
- return res;
+ return resPTS;
}
JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_seek0
diff --git a/src/jogl/native/openmax/omx_tool.c b/src/jogl/native/openmax/omx_tool.c
index 16c43f6a8..26a3b93f1 100644
--- a/src/jogl/native/openmax/omx_tool.c
+++ b/src/jogl/native/openmax/omx_tool.c
@@ -1049,17 +1049,13 @@ void OMXToolBasicAV_SetStream(OMXToolBasicAV_t * pOMXAV, int vBufferNum, const K
DBG_PRINT( "SetStream X\n");
}
-void OMXToolBasicAV_SetStreamEGLImageTexture2D(OMXToolBasicAV_t * pOMXAV, KDint i, GLuint tex, EGLImageKHR image, EGLSyncKHR sync)
+void OMXToolBasicAV_SetStreamEGLImageTexture2D(OMXToolBasicAV_t * pOMXAV, GLuint tex, EGLImageKHR image, EGLSyncKHR sync)
{
if(NULL==pOMXAV) {
JoglCommon_throwNewRuntimeException(0, "OMX instance null\n");
return;
}
- DBG_PRINT( "SetStreamEGLImg %p #%d/%d t:%d i:%p s:%p..\n", pOMXAV, i, pOMXAV->vBufferNum, tex, image, sync);
- if(i<0||i>=pOMXAV->vBufferNum) {
- JoglCommon_throwNewRuntimeException(0, "Buffer index out of range: %d\n", i);
- return;
- }
+ DBG_PRINT( "SetStreamEGLImg %p count %d t:%d i:%p s:%p..\n", pOMXAV, pOMXAV->vBufferNum, tex, image, sync);
kdThreadMutexLock(pOMXAV->mutex);
{