diff options
author | Sven Gothel <[email protected]> | 2023-10-15 07:06:53 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2023-10-15 07:06:53 +0200 |
commit | b1956113f5601b0cc6ac525d3918a0dfa8d240af (patch) | |
tree | b7365f799d5bdad00f8b0f60632884175cff4ef1 /src/demos/com/jogamp/opengl | |
parent | 86210fde931400ff6f1b0a2da48ca031a957df8d (diff) |
Bug 1472: Enhance GLMediaPlayer AV Sync: Utilize SCR aware audio PTS used as master-clock, enabling proper AV sync w/ untouched audio
We can finally utilize the added pass through audio PTS, see commits
- GlueGen 52725b4c6525487f93407f529dc0a758b387a4fc
- JOAL 12029f1ec1d8afa576e1ac61655f318cc37c1d16
This enables us to use the audio PTS as the master-clock and adjust video to the untouched audio.
In case no audio is selected/playing or audio is muted,
we sync merely on the system-clock (SCR) w/o audio.
AV granularity is 22ms, however, since the ALAudioSink PTS may be a little late,
it renders even a slightly better sync in case of too early audio (d_apts < 0).
Since video frames are sync'ed to audio, the resync procedure may result
in a hysteresis swinging into sync. This might be notable at start
and when resumed audio or after seek.
We leave the audio frames untouched to reduce processing burden
and allow non-disrupted listening.
Passed AV sync tests
- Five-minute-sync-test.mp4
- Audio-Video-Sync-Test-Calibration-23.98fps-24fps.mp4
- Audio-Video-Sync-Test-2.mkv
Diffstat (limited to 'src/demos/com/jogamp/opengl')
-rw-r--r-- | src/demos/com/jogamp/opengl/demos/av/MovieSimple.java | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/src/demos/com/jogamp/opengl/demos/av/MovieSimple.java b/src/demos/com/jogamp/opengl/demos/av/MovieSimple.java index 504d97990..9bf984d40 100644 --- a/src/demos/com/jogamp/opengl/demos/av/MovieSimple.java +++ b/src/demos/com/jogamp/opengl/demos/av/MovieSimple.java @@ -34,6 +34,7 @@ import java.net.URI; import java.net.URISyntaxException; import com.jogamp.common.net.Uri; +import com.jogamp.common.os.Clock; import com.jogamp.common.util.InterruptSource; import com.jogamp.graph.curve.Region; import com.jogamp.graph.curve.opengl.GLRegion; @@ -155,6 +156,7 @@ public class MovieSimple implements GLEventListener { final float tfps = null != anim ? anim.getTotalFPS() : 0f; final boolean hasVideo = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID(); final float pts = ( hasVideo ? mPlayer.getVideoPTS() : mPlayer.getAudioPTS() ) / 1000f; + final float scr = ( Clock.currentMillis() - play_t0 ) / 1000f; // Note: MODELVIEW is from [ 0 .. height ] @@ -163,8 +165,8 @@ public class MovieSimple implements GLEventListener { final float aspect = (float)mPlayer.getWidth() / (float)mPlayer.getHeight(); final String ptsPrec = null != regionFPS ? "3.1" : "3.0"; - final String text1 = String.format("%0"+ptsPrec+"f/%0"+ptsPrec+"f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, swap %d", - pts, mPlayer.getDuration() / 1000f, + final String text1 = String.format("%0"+ptsPrec+"f/%0"+ptsPrec+"f/%0"+ptsPrec+"f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, swap %d", + scr, pts, mPlayer.getDuration() / 1000f, mPlayer.getState().toString().toLowerCase(), mPlayer.getPlaySpeed(), mPlayer.getAudioVolume(), aspect, mPlayer.getFramerate(), lfps, tfps, drawable.getGL().getSwapInterval()); final String text2 = String.format("audio: id %d, kbps %d, codec %s", @@ -627,6 +629,7 @@ public class MovieSimple implements GLEventListener { } if( eventMask.isSet(GLMediaPlayer.EventMask.Bit.Play) ) { window.getAnimator().resetFPSCounter(); + ms.play_t0 = Clock.currentMillis(); } boolean destroy = false; @@ -668,6 +671,7 @@ public class MovieSimple implements GLEventListener { } }; public final static MyGLMediaEventListener myGLMediaEventListener = new MyGLMediaEventListener(); + long play_t0 = 0; static boolean loopEOS = false; static boolean origSize; |