Add debug log entry for video player pool usage.

This commit is contained in:
Alex Hart
2022-05-20 14:54:24 -03:00
parent 63f4f0bcec
commit eaa7262b2f
9 changed files with 90 additions and 32 deletions

View File

@@ -121,9 +121,9 @@ public class VideoPlayer extends FrameLayout {
private MediaItem mediaItem;
public void setVideoSource(@NonNull VideoSlide videoSource, boolean autoplay) {
public void setVideoSource(@NonNull VideoSlide videoSource, boolean autoplay, String poolTag) {
if (exoPlayer == null) {
exoPlayer = ApplicationDependencies.getExoPlayerPool().require();
exoPlayer = ApplicationDependencies.getExoPlayerPool().require(poolTag);
exoPlayer.addListener(exoPlayerListener);
exoPlayer.addListener(playerListener);
exoView.setPlayer(exoPlayer);

View File

@@ -10,6 +10,7 @@ import com.google.android.exoplayer2.source.MediaSourceFactory
import com.google.android.exoplayer2.source.ProgressiveMediaSource
import com.google.android.exoplayer2.upstream.DataSource
import com.google.android.exoplayer2.util.MimeTypes
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
import org.thoughtcrime.securesms.net.ContentProxySelector
import org.thoughtcrime.securesms.util.AppForegroundObserver
@@ -81,6 +82,10 @@ abstract class ExoPlayerPool<T : ExoPlayer>(
private val maximumReservedPlayers: Int,
) : AppForegroundObserver.Listener {
companion object {
private val TAG = Log.tag(ExoPlayerPool::class.java)
}
private val pool: MutableMap<T, PoolState> = mutableMapOf()
/**
@@ -89,8 +94,8 @@ abstract class ExoPlayerPool<T : ExoPlayer>(
* @return A player if one is available, otherwise null
*/
@MainThread
fun get(): T? {
return get(allowReserved = false)
fun get(tag: String): T? {
return get(allowReserved = false, tag = tag)
}
/**
@@ -100,8 +105,8 @@ abstract class ExoPlayerPool<T : ExoPlayer>(
* @throws IllegalStateException if no player is available.
*/
@MainThread
fun require(): T {
return checkNotNull(get(allowReserved = true)) { "Required exoPlayer could not be acquired! :: ${poolStats()}" }
fun require(tag: String): T {
return checkNotNull(get(allowReserved = true, tag = tag)) { "Required exoPlayer could not be acquired for $tag! :: ${poolStats()}" }
}
/**
@@ -113,25 +118,26 @@ abstract class ExoPlayerPool<T : ExoPlayer>(
fun pool(exoPlayer: T) {
val poolState = pool[exoPlayer]
if (poolState != null) {
pool[exoPlayer] = poolState.copy(available = true)
pool[exoPlayer] = poolState.copy(available = true, tag = null)
} else {
throw IllegalArgumentException("Tried to return unknown ExoPlayer to pool :: ${poolStats()}")
}
}
@MainThread
private fun get(allowReserved: Boolean): T? {
private fun get(allowReserved: Boolean, tag: String): T? {
val player = findAvailablePlayer(allowReserved)
return if (player == null && pool.size < getMaximumAllowed(allowReserved)) {
val newPlayer = createPlayer()
val poolState = createPoolStateForNewEntry(allowReserved)
val poolState = createPoolStateForNewEntry(allowReserved, tag)
pool[newPlayer] = poolState
newPlayer
} else if (player != null) {
val poolState = pool[player]!!.copy(available = false)
val poolState = pool[player]!!.copy(available = false, tag = tag)
pool[player] = poolState
player
} else {
Log.d(TAG, "Failed to get an ExoPlayer instance for tag: $tag")
null
}
}
@@ -140,11 +146,11 @@ abstract class ExoPlayerPool<T : ExoPlayer>(
return if (allowReserved) getMaxSimultaneousPlayback() else getMaxSimultaneousPlayback() - maximumReservedPlayers
}
private fun createPoolStateForNewEntry(allowReserved: Boolean): PoolState {
private fun createPoolStateForNewEntry(allowReserved: Boolean, tag: String?): PoolState {
return if (allowReserved && pool.none { (_, v) -> v.reserved }) {
PoolState(available = false, reserved = true)
PoolState(available = false, reserved = true, tag = tag)
} else {
PoolState(available = false, reserved = false)
PoolState(available = false, reserved = false, tag = tag)
}
}
@@ -175,39 +181,51 @@ abstract class ExoPlayerPool<T : ExoPlayer>(
}
private fun poolStats(): String {
return getPoolStats().toString()
}
fun getPoolStats(): PoolStats {
val poolStats = PoolStats(
created = pool.size,
maxUnreserved = getMaxSimultaneousPlayback() - maximumReservedPlayers,
maxReserved = maximumReservedPlayers
maxReserved = maximumReservedPlayers,
owners = emptyList()
)
pool.values.fold(poolStats) { acc, state ->
return pool.values.fold(poolStats) { acc, state ->
Log.d(TAG, "$state")
acc.copy(
unreservedAndAvailable = acc.unreservedAndAvailable + if (state.unreservedAndAvailable) 1 else 0,
reservedAndAvailable = acc.reservedAndAvailable + if (state.reservedAndAvailable) 1 else 0,
unreserved = acc.unreserved + if (!state.reserved) 1 else 0,
reserved = acc.reserved + if (state.reserved) 1 else 0
reserved = acc.reserved + if (state.reserved) 1 else 0,
owners = if (!state.available) acc.owners + OwnershipInfo(state.tag!!, state.reserved) else acc.owners
)
}
return poolStats.toString()
}
protected abstract fun getMaxSimultaneousPlayback(): Int
private data class PoolStats(
data class PoolStats(
val created: Int = 0,
val maxUnreserved: Int = 0,
val maxReserved: Int = 0,
val unreservedAndAvailable: Int = 0,
val reservedAndAvailable: Int = 0,
val unreserved: Int = 0,
val reserved: Int = 0
val reserved: Int = 0,
val owners: List<OwnershipInfo>
)
data class OwnershipInfo(
val tag: String,
val isReserved: Boolean
)
private data class PoolState(
val available: Boolean,
val reserved: Boolean
val reserved: Boolean,
val tag: String?
) {
val unreservedAndAvailable = available && !reserved
val reservedAndAvailable = available && reserved