feat(android): cache (#3514)
* feat: android cache * docs: bufferSize * Revert "docs: bufferSize" This reverts commit 09637b134e121b9ca3ffd78f2f5bc657319ed67a. * fix: cacheSize name * feat: singleton android cache * fix: local cache resolve * fix: lint * docs: android cache * chore: merge conflict * fix: lint * chore: useCache button * chore: fix state in the sample * fix: cache factory * chore: update cacheSizeMB docs --------- Co-authored-by: Olivier Bouillet <freeboub@gmail.com>
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
package com.brentvatne.exoplayer
|
||||
|
||||
import android.content.Context
|
||||
import androidx.media3.database.StandaloneDatabaseProvider
|
||||
import androidx.media3.datasource.DataSource
|
||||
import androidx.media3.datasource.HttpDataSource
|
||||
import androidx.media3.datasource.cache.CacheDataSource
|
||||
import androidx.media3.datasource.cache.LeastRecentlyUsedCacheEvictor
|
||||
import androidx.media3.datasource.cache.SimpleCache
|
||||
import java.io.File
|
||||
|
||||
object RNVSimpleCache {
|
||||
// TODO: when to release? how to check if cache is released?
|
||||
private var simpleCache: SimpleCache? = null
|
||||
var cacheDataSourceFactory: DataSource.Factory? = null
|
||||
|
||||
fun setSimpleCache(context: Context, cacheSize: Int, factory: HttpDataSource.Factory) {
|
||||
if (cacheDataSourceFactory != null || cacheSize == 0) return
|
||||
simpleCache = SimpleCache(
|
||||
File(context.cacheDir, "RNVCache"),
|
||||
LeastRecentlyUsedCacheEvictor(
|
||||
cacheSize.toLong() * 1024 * 1024
|
||||
),
|
||||
StandaloneDatabaseProvider(context)
|
||||
)
|
||||
cacheDataSourceFactory =
|
||||
CacheDataSource.Factory()
|
||||
.setCache(simpleCache!!)
|
||||
.setUpstreamDataSourceFactory(factory)
|
||||
}
|
||||
}
|
@@ -105,7 +105,6 @@ import com.brentvatne.react.BuildConfig;
|
||||
import com.brentvatne.react.R;
|
||||
import com.brentvatne.receiver.AudioBecomingNoisyReceiver;
|
||||
import com.brentvatne.receiver.BecomingNoisyListener;
|
||||
import com.facebook.react.bridge.Dynamic;
|
||||
import com.facebook.react.bridge.LifecycleEventListener;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
@@ -188,7 +187,6 @@ public class ReactExoplayerView extends FrameLayout implements
|
||||
private boolean hasDrmFailed = false;
|
||||
private boolean isUsingContentResolution = false;
|
||||
private boolean selectTrackWhenReady = false;
|
||||
|
||||
private int minBufferMs = DefaultLoadControl.DEFAULT_MIN_BUFFER_MS;
|
||||
private int maxBufferMs = DefaultLoadControl.DEFAULT_MAX_BUFFER_MS;
|
||||
private int bufferForPlaybackMs = DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS;
|
||||
@@ -199,6 +197,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
||||
private double minBufferMemoryReservePercent = ReactExoplayerView.DEFAULT_MIN_BUFFER_MEMORY_RESERVE;
|
||||
private Handler mainHandler;
|
||||
private Runnable mainRunnable;
|
||||
private DataSource.Factory cacheDataSourceFactory;
|
||||
|
||||
// Props from React
|
||||
private Uri srcUri;
|
||||
@@ -623,8 +622,11 @@ public class ReactExoplayerView extends FrameLayout implements
|
||||
.setAdEventListener(this)
|
||||
.setAdErrorListener(this)
|
||||
.build();
|
||||
|
||||
DefaultMediaSourceFactory mediaSourceFactory = new DefaultMediaSourceFactory(mediaDataSourceFactory);
|
||||
if (cacheDataSourceFactory != null) {
|
||||
mediaSourceFactory.setDataSourceFactory(cacheDataSourceFactory);
|
||||
}
|
||||
|
||||
if (adsLoader != null) {
|
||||
mediaSourceFactory.setLocalAdInsertionComponents(unusedAdTagUri -> adsLoader, exoPlayerView);
|
||||
}
|
||||
@@ -839,9 +841,17 @@ public class ReactExoplayerView extends FrameLayout implements
|
||||
);
|
||||
break;
|
||||
case CONTENT_TYPE_OTHER:
|
||||
mediaSourceFactory = new ProgressiveMediaSource.Factory(
|
||||
mediaDataSourceFactory
|
||||
);
|
||||
if (uri.toString().startsWith("file://") ||
|
||||
cacheDataSourceFactory == null) {
|
||||
mediaSourceFactory = new ProgressiveMediaSource.Factory(
|
||||
mediaDataSourceFactory
|
||||
);
|
||||
} else {
|
||||
mediaSourceFactory = new ProgressiveMediaSource.Factory(
|
||||
cacheDataSourceFactory
|
||||
);
|
||||
|
||||
}
|
||||
break;
|
||||
case CONTENT_TYPE_RTSP:
|
||||
if (!BuildConfig.USE_EXOPLAYER_RTSP) {
|
||||
@@ -2015,7 +2025,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
||||
exoPlayerView.setHideShutterView(hideShutterView);
|
||||
}
|
||||
|
||||
public void setBufferConfig(int newMinBufferMs, int newMaxBufferMs, int newBufferForPlaybackMs, int newBufferForPlaybackAfterRebufferMs, double newMaxHeapAllocationPercent, double newMinBackBufferMemoryReservePercent, double newMinBufferMemoryReservePercent, int newBackBufferDurationMs) {
|
||||
public void setBufferConfig(int newMinBufferMs, int newMaxBufferMs, int newBufferForPlaybackMs, int newBufferForPlaybackAfterRebufferMs, double newMaxHeapAllocationPercent, double newMinBackBufferMemoryReservePercent, double newMinBufferMemoryReservePercent, int newBackBufferDurationMs, int cacheSize) {
|
||||
minBufferMs = newMinBufferMs;
|
||||
maxBufferMs = newMaxBufferMs;
|
||||
bufferForPlaybackMs = newBufferForPlaybackMs;
|
||||
@@ -2023,6 +2033,17 @@ public class ReactExoplayerView extends FrameLayout implements
|
||||
maxHeapAllocationPercent = newMaxHeapAllocationPercent;
|
||||
minBackBufferMemoryReservePercent = newMinBackBufferMemoryReservePercent;
|
||||
minBufferMemoryReservePercent = newMinBufferMemoryReservePercent;
|
||||
if (cacheSize > 0) {
|
||||
RNVSimpleCache.INSTANCE.setSimpleCache(
|
||||
this.getContext(),
|
||||
cacheSize,
|
||||
buildHttpDataSourceFactory(false)
|
||||
);
|
||||
cacheDataSourceFactory = RNVSimpleCache.INSTANCE.getCacheDataSourceFactory();
|
||||
} else {
|
||||
cacheDataSourceFactory = null;
|
||||
}
|
||||
|
||||
backBufferDurationMs = newBackBufferDurationMs;
|
||||
releasePlayer();
|
||||
initializePlayer();
|
||||
|
@@ -59,6 +59,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
||||
private static final String PROP_AUDIO_OUTPUT = "audioOutput";
|
||||
private static final String PROP_VOLUME = "volume";
|
||||
private static final String PROP_BUFFER_CONFIG = "bufferConfig";
|
||||
private static final String PROP_BUFFER_CONFIG_CACHE_SIZE = "cacheSizeMB";
|
||||
private static final String PROP_BUFFER_CONFIG_MIN_BUFFER_MS = "minBufferMs";
|
||||
private static final String PROP_BUFFER_CONFIG_MAX_BUFFER_MS = "maxBufferMs";
|
||||
private static final String PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_MS = "bufferForPlaybackMs";
|
||||
@@ -402,6 +403,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
||||
|
||||
@ReactProp(name = PROP_BUFFER_CONFIG)
|
||||
public void setBufferConfig(final ReactExoplayerView videoView, @Nullable ReadableMap bufferConfig) {
|
||||
int cacheSize = 0;
|
||||
int minBufferMs = DefaultLoadControl.DEFAULT_MIN_BUFFER_MS;
|
||||
int maxBufferMs = DefaultLoadControl.DEFAULT_MAX_BUFFER_MS;
|
||||
int bufferForPlaybackMs = DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS;
|
||||
@@ -412,6 +414,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
||||
double minBufferMemoryReservePercent = ReactExoplayerView.DEFAULT_MIN_BUFFER_MEMORY_RESERVE;
|
||||
|
||||
if (bufferConfig != null) {
|
||||
cacheSize = ReactBridgeUtils.safeGetInt(bufferConfig, PROP_BUFFER_CONFIG_CACHE_SIZE, 0);
|
||||
minBufferMs = ReactBridgeUtils.safeGetInt(bufferConfig, PROP_BUFFER_CONFIG_MIN_BUFFER_MS, minBufferMs);
|
||||
maxBufferMs = ReactBridgeUtils.safeGetInt(bufferConfig, PROP_BUFFER_CONFIG_MAX_BUFFER_MS, maxBufferMs);
|
||||
bufferForPlaybackMs = ReactBridgeUtils.safeGetInt(bufferConfig, PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_MS, bufferForPlaybackMs);
|
||||
@@ -420,7 +423,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
||||
minBackBufferMemoryReservePercent = ReactBridgeUtils.safeGetDouble(bufferConfig, PROP_BUFFER_CONFIG_MIN_BACK_BUFFER_MEMORY_RESERVE_PERCENT, minBackBufferMemoryReservePercent);
|
||||
minBufferMemoryReservePercent = ReactBridgeUtils.safeGetDouble(bufferConfig, PROP_BUFFER_CONFIG_MIN_BUFFER_MEMORY_RESERVE_PERCENT, minBufferMemoryReservePercent);
|
||||
backBufferDurationMs = ReactBridgeUtils.safeGetInt(bufferConfig, PROP_BUFFER_CONFIG_BACK_BUFFER_DURATION_MS, backBufferDurationMs);
|
||||
videoView.setBufferConfig(minBufferMs, maxBufferMs, bufferForPlaybackMs, bufferForPlaybackAfterRebufferMs, maxHeapAllocationPercent, minBackBufferMemoryReservePercent, minBufferMemoryReservePercent, backBufferDurationMs);
|
||||
videoView.setBufferConfig(minBufferMs, maxBufferMs, bufferForPlaybackMs, bufferForPlaybackAfterRebufferMs, maxHeapAllocationPercent, minBackBufferMemoryReservePercent, minBufferMemoryReservePercent, backBufferDurationMs, cacheSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user