diff options
author | Sven Gothel <[email protected]> | 2013-08-24 17:56:49 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2013-08-24 17:56:49 +0200 |
commit | d0e01cb5c0ec3e48b8a9b9b79a7795b214c6e3ea (patch) | |
tree | 9594bb101e06ccd5e6ea1abdd5ea72777263bc83 /src/jogl/native/libav | |
parent | deae6def7a818d3189bec403f8cde2ad9936d416 (diff) |
GLMediaPlayer Multithreaded Decoding: GLMediaPlayer* (Part-6) - DONE
Multithreaded decoding and API should be considered stable by now,
minor changes may apply if Android/OMX impl. requires it.
We still need to solve TODO's as listed below, copied from 474ce65081ecd452215bc07ab866666cb11ca8b1.
+++
- *TextureFrame OO changes:
- TextureFrame extends TimeFrameI
- GLMediaPlayerImpl*
- Adapt to Ringbuffer changes of GlueGen commit f9f881e59c78e3036cb3f956bc97cfc3197f620d
- Fix impl. method's API doc
- getNextTextureImpl(..) returns video PTS
- Fix audio-only playback
- frame dropping shall only happen if:
- previous frame has not been dropped
- frame is too later
- one decoded frame is already available
- Don't block for decoder anymore:
- nextFrame = "videoFramesDecoded.getBlocking() -> videoFramesDecoded.get()";
No 'next decoded frame avail' only could mean:
- slow decoding/hardware
- slow transport
hence we shall not block rendering.
- Add DEBUG output if using last frame
- Add integer property 'jogl.debug.GLMediaPlayer.StreamWorker.delay' in milliseconds
to simulate slow decoding, i.e. delay is added in StreamWorker after decoding
before pushing new frame to Ringbuffer.
- FFMPEGMediaPlayer:
- audioFrameLimitWithVideo 128 -> 64
- audioFrameLimitAudioOnly 128 -> 32
- uses AudioSink's 'enqueueData(int pts, ByteBuffer bytes, int byteCount)'
- fixes for audio-only playback
+++
Working Tests: MovieSimple and MovieCube
TODO-1: Fix
- Android
- OMXGLMediaPlayer
TODO-2:
- Fix issue where async audio frames arrive much later than 1st video frame, i.e. around 300ms.
- Default TextureCount .. maybe 3 ?
- Adding Audio synchronization ?
- Find 'truth' about correlation of audio and video PTS values,
currently, we assume both to be unrelated ?
Diffstat (limited to 'src/jogl/native/libav')
-rw-r--r-- | src/jogl/native/libav/ffmpeg_tool.h | 4 | ||||
-rw-r--r-- | src/jogl/native/libav/jogamp_opengl_util_av_impl_FFMPEGMediaPlayer.c | 44 |
2 files changed, 28 insertions, 20 deletions
diff --git a/src/jogl/native/libav/ffmpeg_tool.h b/src/jogl/native/libav/ffmpeg_tool.h index 76de406ae..013cc0cf2 100644 --- a/src/jogl/native/libav/ffmpeg_tool.h +++ b/src/jogl/native/libav/ffmpeg_tool.h @@ -73,10 +73,10 @@ typedef void (APIENTRYP PFNGLFINISH) (void); /** Default number of audio frames per video frame. Sync w/ FFMPEGMediaPlayer.AV_DEFAULT_AFRAMES. */ #define AV_DEFAULT_AFRAMES 8 -/** Constant PTS marking an invalid PTS, i.e. Integer.MIN_VALUE == 0x80000000 == {@value}. Sync w/ TextureFrame.INVALID_PTS */ +/** Constant PTS marking an invalid PTS, i.e. Integer.MIN_VALUE == 0x80000000 == {@value}. Sync w/ TimeFrameI.INVALID_PTS */ #define INVALID_PTS 0x80000000 -/** Constant PTS marking the end of the stream, i.e. Integer.MIN_VALUE - 1 == 0x7FFFFFFF == {@value}. Sync w/ TextureFrame.END_OF_STREAM_PTS */ +/** 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 */ 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 99ef02da5..63164e547 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 @@ -234,6 +234,12 @@ static void _updateJavaAttributes(JNIEnv *env, jobject instance, FFMPEGToolBasic w = 0; h = 0; } + (*env)->CallVoidMethod(env, instance, jni_mid_updateAttributes2, + pAV->vPixFmt, pAV->vBufferPlanes, + pAV->vBitsPerPixel, pAV->vBytesPerPixelPerPlane, + pAV->vLinesize[0], pAV->vLinesize[1], pAV->vLinesize[2], + pAV->vTexWidth[0], pAV->vTexWidth[1], pAV->vTexWidth[2], h, + pAV->aFramesPerVideoFrame, pAV->aSampleFmt, pAV->aSampleRate, pAV->aChannels); (*env)->CallVoidMethod(env, instance, jni_mid_updateAttributes1, pAV->vid, pAV->aid, w, h, @@ -241,12 +247,6 @@ static void _updateJavaAttributes(JNIEnv *env, jobject instance, FFMPEGToolBasic pAV->fps, pAV->frames_video, pAV->frames_audio, pAV->duration, (*env)->NewStringUTF(env, pAV->vcodec), (*env)->NewStringUTF(env, pAV->acodec) ); - (*env)->CallVoidMethod(env, instance, jni_mid_updateAttributes2, - pAV->vPixFmt, pAV->vBufferPlanes, - pAV->vBitsPerPixel, pAV->vBytesPerPixelPerPlane, - pAV->vLinesize[0], pAV->vLinesize[1], pAV->vLinesize[2], - pAV->vTexWidth[0], pAV->vTexWidth[1], pAV->vTexWidth[2], - pAV->aFramesPerVideoFrame, pAV->aSampleFmt, pAV->aSampleRate, pAV->aChannels); } } @@ -392,7 +392,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_ini jni_mid_pushSound = (*env)->GetMethodID(env, ffmpegMediaPlayerClazz, "pushSound", "(Ljava/nio/ByteBuffer;II)V"); jni_mid_updateAttributes1 = (*env)->GetMethodID(env, ffmpegMediaPlayerClazz, "updateAttributes", "(IIIIIIIFIIILjava/lang/String;Ljava/lang/String;)V"); - jni_mid_updateAttributes2 = (*env)->GetMethodID(env, ffmpegMediaPlayerClazz, "updateAttributes2", "(IIIIIIIIIIIIII)V"); + jni_mid_updateAttributes2 = (*env)->GetMethodID(env, ffmpegMediaPlayerClazz, "updateAttributes2", "(IIIIIIIIIIIIIII)V"); if(jni_mid_pushSound == NULL || jni_mid_updateAttributes1 == NULL || @@ -858,9 +858,10 @@ JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_readNex if( AVERROR_EOF == avRes || ( pAV->pFormatCtx->pb && pAV->pFormatCtx->pb->eof_reached ) ) { resPTS = END_OF_STREAM_PTS; } else if( 0 <= avRes ) { + /** if( pAV->verbose ) { fprintf(stderr, "P: ptr %p, size %d\n", packet.data, packet.size); - } + } */ if(packet.stream_index==pAV->aid) { // Decode audio frame if(NULL == pAV->pAFrames) { // no audio registered @@ -1206,38 +1207,43 @@ JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_seek0 { const FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr)); const int64_t pos0 = pAV->vPTS; - const int64_t pts0 = pAV->pVFrame->pkt_pts; + int64_t pts0; int streamID; AVRational time_base; if( pAV->vid >= 0 ) { streamID = pAV->vid; time_base = pAV->pVStream->time_base; + pts0 = pAV->pVFrame->pkt_pts; } else if( pAV->aid >= 0 ) { streamID = pAV->aid; time_base = pAV->pAStream->time_base; + pts0 = pAV->pAFrames[pAV->aFrameCurrent]->pkt_pts; } else { return pAV->vPTS; } int64_t pts1 = (int64_t) (pos1 * (int64_t) time_base.den) / (1000 * (int64_t) time_base.num); + if(pAV->verbose) { + fprintf(stderr, "SEEK: vid %d, aid %d, pos1 %d, pts: %ld -> %ld\n", pAV->vid, pAV->aid, pos1, pts0, pts1); + } int flags = 0; if(pos1 < pos0) { flags |= AVSEEK_FLAG_BACKWARD; } int res; if(HAS_FUNC(sp_av_seek_frame)) { - if(pos1 < pos0) { - flags |= AVSEEK_FLAG_BACKWARD; + if(pAV->verbose) { + fprintf(stderr, "SEEK.0: pre : s %ld / %ld -> t %d / %ld\n", pos0, pts0, pos1, pts1); } - fprintf(stderr, "SEEK.0: pre : s %ld / %ld -> t %ld / %ld\n", pos0, pts0, pos1, pts1); sp_av_seek_frame(pAV->pFormatCtx, streamID, pts1, flags); - } else if(HAS_FUNC(sp_avformat_seek_file)) { int64_t ptsD = pts1 - pts0; int64_t seek_min = ptsD > 0 ? pts1 - ptsD : INT64_MIN; int64_t seek_max = ptsD < 0 ? pts1 - ptsD : INT64_MAX; - fprintf(stderr, "SEEK.1: pre : s %ld / %ld -> t %ld / %ld [%ld .. %ld]\n", - pos0, pts0, pos1, pts1, seek_min, seek_max); + if(pAV->verbose) { + fprintf(stderr, "SEEK.1: pre : s %ld / %ld -> t %d / %ld [%ld .. %ld]\n", + pos0, pts0, pos1, pts1, seek_min, seek_max); + } res = sp_avformat_seek_file(pAV->pFormatCtx, -1, seek_min, pts1, seek_max, flags); } if(NULL != pAV->pVCodecCtx) { @@ -1246,9 +1252,11 @@ JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_seek0 if(NULL != pAV->pACodecCtx) { sp_avcodec_flush_buffers( pAV->pACodecCtx ); } - const jint vPTS = my_av_q2i32( pAV->pVFrame->pkt_pts * 1000, pAV->pVStream->time_base); - fprintf(stderr, "SEEK: post : res %d, u %ld, p %ld\n", res, vPTS, pAV->pVFrame->pkt_pts); - return vPTS; + const jint rPTS = my_av_q2i32( ( pAV->vid >= 0 ? pAV->pVFrame->pkt_pts : pAV->pAFrames[pAV->aFrameCurrent]->pkt_pts ) * 1000, time_base); + if(pAV->verbose) { + fprintf(stderr, "SEEK: post : res %d, u %ld\n", res, rPTS); + } + return rPTS; } JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_getVideoPTS0 |