fix(android): implement live configuration management (#3792)

* perf: ensure we do not provide callback to native if no callback provided from app

* chore: rework bufferConfig to make it more generic and reduce ReactExoplayerView code size

* chore: improve issue template

* fix(android): avoid video view flickering at playback startup

* feat(android): implement live buffer configuration

* chore: fix linter
This commit is contained in:
Olivier Bouillet
2024-05-20 16:18:20 +02:00
committed by GitHub
parent 8fdc52372c
commit e16730de11
7 changed files with 110 additions and 1 deletions

View File

@@ -1,6 +1,7 @@
package com.brentvatne.common.api
import com.brentvatne.common.toolbox.ReactBridgeUtils.safeGetDouble
import com.brentvatne.common.toolbox.ReactBridgeUtils.safeGetFloat
import com.brentvatne.common.toolbox.ReactBridgeUtils.safeGetInt
import com.facebook.react.bridge.ReadableMap
@@ -20,6 +21,35 @@ class BufferConfig {
var minBackBufferMemoryReservePercent = BufferConfigPropUnsetDouble
var minBufferMemoryReservePercent = BufferConfigPropUnsetDouble
var live: Live = Live()
class Live {
var maxPlaybackSpeed: Float = BufferConfigPropUnsetDouble.toFloat()
var minPlaybackSpeed: Float = BufferConfigPropUnsetDouble.toFloat()
var maxOffsetMs: Long = BufferConfigPropUnsetInt.toLong()
var minOffsetMs: Long = BufferConfigPropUnsetInt.toLong()
var targetOffsetMs: Long = BufferConfigPropUnsetInt.toLong()
companion object {
private val PROP_BUFFER_CONFIG_LIVE_MAX_PLAYBACK_SPEED = "maxPlaybackSpeed"
private val PROP_BUFFER_CONFIG_LIVE_MIN_PLAYBACK_SPEED = "minPlaybackSpeed"
private val PROP_BUFFER_CONFIG_LIVE_MAX_OFFSET_MS = "maxOffsetMs"
private val PROP_BUFFER_CONFIG_LIVE_MIN_OFFSET_MS = "minOffsetMs"
private val PROP_BUFFER_CONFIG_LIVE_TARGET_OFFSET_MS = "targetOffsetMs"
@JvmStatic
fun parse(src: ReadableMap?): Live {
val live = Live()
live.maxPlaybackSpeed = safeGetFloat(src, PROP_BUFFER_CONFIG_LIVE_MAX_PLAYBACK_SPEED, BufferConfigPropUnsetDouble.toFloat())
live.minPlaybackSpeed = safeGetFloat(src, PROP_BUFFER_CONFIG_LIVE_MIN_PLAYBACK_SPEED, BufferConfigPropUnsetDouble.toFloat())
live.maxOffsetMs = safeGetInt(src, PROP_BUFFER_CONFIG_LIVE_MAX_OFFSET_MS, BufferConfigPropUnsetInt).toLong()
live.minOffsetMs = safeGetInt(src, PROP_BUFFER_CONFIG_LIVE_MIN_OFFSET_MS, BufferConfigPropUnsetInt).toLong()
live.targetOffsetMs = safeGetInt(src, PROP_BUFFER_CONFIG_LIVE_TARGET_OFFSET_MS, BufferConfigPropUnsetInt).toLong()
return live
}
}
}
companion object {
val BufferConfigPropUnsetInt = -1
val BufferConfigPropUnsetDouble = -1.0
@@ -33,6 +63,7 @@ class BufferConfig {
private val PROP_BUFFER_CONFIG_MIN_BACK_BUFFER_MEMORY_RESERVE_PERCENT = "minBackBufferMemoryReservePercent"
private val PROP_BUFFER_CONFIG_MIN_BUFFER_MEMORY_RESERVE_PERCENT = "minBufferMemoryReservePercent"
private val PROP_BUFFER_CONFIG_BACK_BUFFER_DURATION_MS = "backBufferDurationMs"
private val PROP_BUFFER_CONFIG_LIVE = "live"
@JvmStatic
fun parse(src: ReadableMap?): BufferConfig {
@@ -59,6 +90,7 @@ class BufferConfig {
BufferConfigPropUnsetDouble
)
bufferConfig.backBufferDurationMs = safeGetInt(src, PROP_BUFFER_CONFIG_BACK_BUFFER_DURATION_MS, BufferConfigPropUnsetInt)
bufferConfig.live = Live.parse(src.getMap(PROP_BUFFER_CONFIG_LIVE))
}
return bufferConfig
}

View File

@@ -0,0 +1,36 @@
package com.brentvatne.exoplayer
import androidx.media3.common.MediaItem.LiveConfiguration
import com.brentvatne.common.api.BufferConfig
import com.brentvatne.common.api.BufferConfig.Live
/**
* Helper functions to create exoplayer configuration
*/
object ConfigurationUtils {
/**
* Create a media3.LiveConfiguration.Builder from parsed BufferConfig
*/
@JvmStatic
fun getLiveConfiguration(bufferConfig: BufferConfig): LiveConfiguration.Builder {
val liveConfiguration = LiveConfiguration.Builder()
val live: Live = bufferConfig.live
if (bufferConfig.live.maxOffsetMs >= 0) {
liveConfiguration.setMaxOffsetMs(live.maxOffsetMs)
}
if (bufferConfig.live.maxPlaybackSpeed >= 0) {
liveConfiguration.setMaxPlaybackSpeed(live.maxPlaybackSpeed)
}
if (bufferConfig.live.targetOffsetMs >= 0) {
liveConfiguration.setTargetOffsetMs(live.targetOffsetMs)
}
if (bufferConfig.live.minOffsetMs >= 0) {
liveConfiguration.setMinOffsetMs(live.minOffsetMs)
}
if (bufferConfig.live.minPlaybackSpeed >= 0) {
liveConfiguration.setMinPlaybackSpeed(live.minPlaybackSpeed)
}
return liveConfiguration
}
}

View File

@@ -965,6 +965,9 @@ public class ReactExoplayerView extends FrameLayout implements
);
}
MediaItem.LiveConfiguration.Builder liveConfiguration = ConfigurationUtils.getLiveConfiguration(bufferConfig);
mediaItemBuilder.setLiveConfiguration(liveConfiguration.build());
MediaSource.Factory mediaSourceFactory;
DrmSessionManagerProvider drmProvider;
List<StreamKey> streamKeys = new ArrayList();