diff options
author | Sven Gothel <[email protected]> | 2013-08-10 09:14:19 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2013-08-10 09:14:19 +0200 |
commit | 6332e13b2f0aa9818d37802302f04c90a4fa4239 (patch) | |
tree | b615630b4a886270721f82636a323ec36dac341c /src/jogl/native | |
parent | 590d78dc2ff24ce80976a30e35a99c06ef6750b0 (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.h | 8 | ||||
-rw-r--r-- | src/jogl/native/libav/jogamp_opengl_util_av_impl_FFMPEGMediaPlayer.c | 59 | ||||
-rw-r--r-- | src/jogl/native/openmax/omx_tool.c | 8 |
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); { |