Skip to content

Commit

Permalink
Integrate Media3 workaround for #515 on API 34
Browse files Browse the repository at this point in the history
  • Loading branch information
MGaetan89 committed Jul 16, 2024
1 parent 6de491e commit 19bfce9
Showing 1 changed file with 64 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@
package ch.srgssr.pillarbox.ui.widget.player

import android.content.Context
import android.graphics.Canvas
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.view.SurfaceControl
import android.view.SurfaceView
import android.window.SurfaceSyncGroup
import androidx.annotation.RequiresApi
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
Expand Down Expand Up @@ -179,6 +186,12 @@ private fun AndroidPlayerSurfaceView(player: Player, modifier: Modifier = Modifi
* Player surface view
*/
private class PlayerSurfaceView(context: Context) : SurfaceView(context) {
private val playerListener = PlayerListener()
private val surfaceSyncGroupV34 = when {
isInEditMode -> null
needSurfaceSyncWorkaround() -> SurfaceSyncGroupCompatV34()
else -> null
}

/**
* Player if null is passed just clear surface
Expand All @@ -187,8 +200,59 @@ private class PlayerSurfaceView(context: Context) : SurfaceView(context) {
set(value) {
if (field != value) {
field?.clearVideoSurfaceView(this)
field?.removeListener(playerListener)
value?.setVideoSurfaceView(this)
value?.addListener(playerListener)
}
field = value
}

override fun dispatchDraw(canvas: Canvas) {
super.dispatchDraw(canvas)

if (needSurfaceSyncWorkaround()) {
surfaceSyncGroupV34?.maybeMarkSyncReadyAndClear()
}
}

// Workaround for a surface sync issue on API 34: https://github.com/androidx/media/issues/1237
// Imported from https://github.com/androidx/media/commit/30cb76269a67e09f6e1662ea9ead6aac70667028
private fun needSurfaceSyncWorkaround(): Boolean {
return Build.VERSION.SDK_INT == Build.VERSION_CODES.UPSIDE_DOWN_CAKE
}

private inner class PlayerListener : Player.Listener {
private val mainLooperHandler = Handler(Looper.getMainLooper())

override fun onSurfaceSizeChanged(width: Int, height: Int) {
if (needSurfaceSyncWorkaround()) {
surfaceSyncGroupV34?.postRegister(mainLooperHandler, this@PlayerSurfaceView)
}
}
}

@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
private class SurfaceSyncGroupCompatV34 {
private var surfaceSyncGroup: SurfaceSyncGroup? = null

fun postRegister(
mainLooperHandler: Handler,
surfaceView: SurfaceView,
) {
mainLooperHandler.post {
// The SurfaceView isn't attached to a window, so don't apply the workaround.
val rootSurfaceControl = surfaceView.getRootSurfaceControl() ?: return@post

surfaceSyncGroup = SurfaceSyncGroup("exo-sync-b-334901521")
surfaceSyncGroup?.add(rootSurfaceControl) {}
surfaceView.invalidate()
rootSurfaceControl.applyTransactionOnDraw(SurfaceControl.Transaction())
}
}

fun maybeMarkSyncReadyAndClear() {
surfaceSyncGroup?.markSyncReady()
surfaceSyncGroup = null
}
}
}

0 comments on commit 19bfce9

Please sign in to comment.