diff --git a/android/src/main/java/com/brentvatne/common/api/BufferConfig.kt b/android/src/main/java/com/brentvatne/common/api/BufferConfig.kt index 4cb33ea4..17f54c62 100644 --- a/android/src/main/java/com/brentvatne/common/api/BufferConfig.kt +++ b/android/src/main/java/com/brentvatne/common/api/BufferConfig.kt @@ -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 diff --git a/android/src/main/java/com/brentvatne/exoplayer/DefaultReactExoplayerConfig.kt b/android/src/main/java/com/brentvatne/exoplayer/DefaultReactExoplayerConfig.kt index 12c0ddf8..435e2fc2 100644 --- a/android/src/main/java/com/brentvatne/exoplayer/DefaultReactExoplayerConfig.kt +++ b/android/src/main/java/com/brentvatne/exoplayer/DefaultReactExoplayerConfig.kt @@ -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) diff --git a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerConfig.kt b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerConfig.kt index 6f5e65ba..4cc47d5f 100644 --- a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerConfig.kt +++ b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerConfig.kt @@ -7,4 +7,6 @@ interface ReactExoplayerConfig { fun buildLoadErrorHandlingPolicy(minLoadRetryCount: Int): LoadErrorHandlingPolicy var disableDisconnectError: Boolean val bandwidthMeter: DefaultBandwidthMeter + var initialBitrate: Long? + fun setInitialBitrate(bitrate: Long) } diff --git a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java index c3bbc95e..7760d1bb 100644 --- a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -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) diff --git a/docs/bun.lockb b/docs/bun.lockb index 4c9665a2..0536e71e 100755 Binary files a/docs/bun.lockb and b/docs/bun.lockb differ diff --git a/docs/pages/component/props.mdx b/docs/pages/component/props.mdx index 10efba93..e85d38c8 100644 --- a/docs/pages/component/props.mdx +++ b/docs/pages/component/props.mdx @@ -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` diff --git a/src/types/video.ts b/src/types/video.ts index d14fe7e2..1be6775e 100644 --- a/src/types/video.ts +++ b/src/types/video.ts @@ -145,6 +145,7 @@ export type BufferConfig = { maxHeapAllocationPercent?: number; minBackBufferMemoryReservePercent?: number; minBufferMemoryReservePercent?: number; + initialBitrate?: number; // Android cacheSizeMB?: number; live?: BufferConfigLive; };