feat(android): initial bitrate (#4480)

* feat(android): implement initialBitrate

* refactor: reorder type

* docs: add initialBitrate section

* fix: lint

* refactor: move `initialBitrate` into `source.bufferConfig`
This commit is contained in:
Kamil Moskała
2025-04-06 16:16:58 +02:00
committed by GitHub
parent d2e5d9c64e
commit 41ddc5c27a
7 changed files with 43 additions and 15 deletions

View File

@@ -20,6 +20,7 @@ class BufferConfig {
var maxHeapAllocationPercent = BufferConfigPropUnsetDouble
var minBackBufferMemoryReservePercent = BufferConfigPropUnsetDouble
var minBufferMemoryReservePercent = BufferConfigPropUnsetDouble
var initialBitrate = BufferConfigPropUnsetInt
var live: Live = Live()
@@ -36,6 +37,7 @@ class BufferConfig {
maxHeapAllocationPercent == other.maxHeapAllocationPercent &&
minBackBufferMemoryReservePercent == other.minBackBufferMemoryReservePercent &&
minBufferMemoryReservePercent == other.minBufferMemoryReservePercent &&
initialBitrate == other.initialBitrate &&
live == other.live
)
}
@@ -91,6 +93,7 @@ class BufferConfig {
private const val PROP_BUFFER_CONFIG_MIN_BACK_BUFFER_MEMORY_RESERVE_PERCENT = "minBackBufferMemoryReservePercent"
private const val PROP_BUFFER_CONFIG_MIN_BUFFER_MEMORY_RESERVE_PERCENT = "minBufferMemoryReservePercent"
private const val PROP_BUFFER_CONFIG_BACK_BUFFER_DURATION_MS = "backBufferDurationMs"
private const val PROP_BUFFER_CONFIG_INITIAL_BITRATE = "initialBitrate"
private const val PROP_BUFFER_CONFIG_LIVE = "live"
@JvmStatic
@@ -118,6 +121,7 @@ class BufferConfig {
BufferConfigPropUnsetDouble
)
bufferConfig.backBufferDurationMs = safeGetInt(src, PROP_BUFFER_CONFIG_BACK_BUFFER_DURATION_MS, BufferConfigPropUnsetInt)
bufferConfig.initialBitrate = safeGetInt(src, PROP_BUFFER_CONFIG_INITIAL_BITRATE, BufferConfigPropUnsetInt)
bufferConfig.live = Live.parse(src.getMap(PROP_BUFFER_CONFIG_LIVE))
}
return bufferConfig

View File

@@ -5,13 +5,26 @@ import androidx.media3.exoplayer.upstream.DefaultBandwidthMeter
import androidx.media3.exoplayer.upstream.DefaultLoadErrorHandlingPolicy
import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy
class DefaultReactExoplayerConfig(context: Context) : ReactExoplayerConfig {
class DefaultReactExoplayerConfig(private val context: Context, override var initialBitrate: Long? = null) : ReactExoplayerConfig {
private var bandWidthMeter: DefaultBandwidthMeter = createBandwidthMeter(initialBitrate)
private var bandWidthMeter: DefaultBandwidthMeter = DefaultBandwidthMeter.Builder(context).build()
override var disableDisconnectError: Boolean = false
override val bandwidthMeter: DefaultBandwidthMeter
get() = bandWidthMeter
private fun createBandwidthMeter(bitrate: Long?): DefaultBandwidthMeter =
DefaultBandwidthMeter.Builder(context)
.setInitialBitrateEstimate(bitrate ?: DefaultBandwidthMeter.DEFAULT_INITIAL_BITRATE_ESTIMATE)
.build()
override fun setInitialBitrate(bitrate: Long) {
if (initialBitrate == bitrate) return
initialBitrate = bitrate
bandWidthMeter = createBandwidthMeter(bitrate)
}
override fun buildLoadErrorHandlingPolicy(minLoadRetryCount: Int): LoadErrorHandlingPolicy =
if (disableDisconnectError) {
ReactExoplayerLoadErrorHandlingPolicy(minLoadRetryCount)

View File

@@ -7,4 +7,6 @@ interface ReactExoplayerConfig {
fun buildLoadErrorHandlingPolicy(minLoadRetryCount: Int): LoadErrorHandlingPolicy
var disableDisconnectError: Boolean
val bandwidthMeter: DefaultBandwidthMeter
var initialBitrate: Long?
fun setInitialBitrate(bitrate: Long)
}

View File

@@ -177,7 +177,7 @@ public class ReactExoplayerView extends FrameLayout implements
protected final VideoEventEmitter eventEmitter;
private final ReactExoplayerConfig config;
private final DefaultBandwidthMeter bandwidthMeter;
private DefaultBandwidthMeter bandwidthMeter;
private LegacyPlayerControlView playerControlView;
private View playPauseControlContainer;
private Player.Listener eventListener;
@@ -849,6 +849,13 @@ public class ReactExoplayerView extends FrameLayout implements
allocator,
source.getBufferConfig()
);
long initialBitrate = source.getBufferConfig().getInitialBitrate();
if (initialBitrate > 0) {
config.setInitialBitrate(initialBitrate);
this.bandwidthMeter = config.getBandwidthMeter();
}
DefaultRenderersFactory renderersFactory =
new DefaultRenderersFactory(getContext())
.setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF)

Binary file not shown.

View File

@@ -985,18 +985,19 @@ source={{
Adjust the buffer settings. This prop takes an object with one or more of the properties listed below.
| Property | Type | Description |
|-----------------------------------|--------|---------------------------------------------------------------------------------------------------------------------------|
| minBufferMs | number | Minimum duration of media that the player will attempt to buffer at all times, in milliseconds. |
| maxBufferMs | number | Maximum duration of media that the player will attempt to buffer, in milliseconds. |
| bufferForPlaybackMs | number | Duration of media that must be buffered for playback to start or resume following a user action, in milliseconds. |
| bufferForPlaybackAfterRebufferMs | number | Duration of media that must be buffered for playback to resume after a rebuffer, in milliseconds. |
| backBufferDurationMs | number | Duration of buffer to keep before the current position, allowing rewinding without rebuffering. |
| maxHeapAllocationPercent | number | Percentage of available heap that the video can use to buffer, between 0 and 1. |
| minBackBufferMemoryReservePercent | number | Percentage of available app memory at which during startup the back buffer will be disabled, between 0 and 1. |
| minBufferMemoryReservePercent | number | Percentage of available app memory to keep in reserve, preventing buffer usage, between 0 and 1. |
| cacheSizeMB | number | Cache size in MB, preventing new src requests and saving bandwidth while repeating videos, or 0 to disable. Android only. |
| live | object | Object containing another config set for live playback configuration. |
| Property | Type | Description |
|----------------------------------|--------|------------------------------------------------------------------------------------------------------------------------------------------------|
| minBufferMs | number | Minimum duration of media that the player will attempt to buffer at all times, in milliseconds. |
| maxBufferMs | number | Maximum duration of media that the player will attempt to buffer, in milliseconds. |
| bufferForPlaybackMs | number | Duration of media that must be buffered for playback to start or resume following a user action, in milliseconds. |
| bufferForPlaybackAfterRebufferMs | number | Duration of media that must be buffered for playback to resume after a rebuffer, in milliseconds. |
| backBufferDurationMs | number | Duration of buffer to keep before the current position, allowing rewinding without rebuffering. |
| maxHeapAllocationPercent | number | Percentage of available heap that the video can use to buffer, between 0 and 1. |
| minBackBufferMemoryReservePercent| number | Percentage of available app memory at which during startup the back buffer will be disabled, between 0 and 1. |
| minBufferMemoryReservePercent | number | Percentage of available app memory to keep in reserve, preventing buffer usage, between 0 and 1. |
| initialBitrate | number | Initial bitrate in bits per second (Android only). Defaults to 1_000_000. Used only at start, then ABR (Adaptive Bitrate Streaming) takes over.|
| cacheSizeMB | number | Cache size in MB, preventing new src requests and saving bandwidth while repeating videos, or 0 to disable. Android only. |
| live | object | Object containing another config set for live playback configuration. |
#### `minLoadRetryCount`

View File

@@ -145,6 +145,7 @@ export type BufferConfig = {
maxHeapAllocationPercent?: number;
minBackBufferMemoryReservePercent?: number;
minBufferMemoryReservePercent?: number;
initialBitrate?: number; // Android
cacheSizeMB?: number;
live?: BufferConfigLive;
};