diff --git a/README.md b/README.md index 564423f8..c0a34da6 100644 --- a/README.md +++ b/README.md @@ -386,6 +386,8 @@ maxBufferMs | number | The default maximum duration of media that the player wil bufferForPlaybackMs | number | The default duration of media that must be buffered for playback to start or resume following a user action such as a seek, in milliseconds. bufferForPlaybackAfterRebufferMs | number | The default duration of media that must be buffered for playback to resume after a rebuffer, in milliseconds. A rebuffer is defined to be caused by buffer depletion rather than a user action. maxHeapAllocationPercent | number | The percentage of available heap that the video can use to buffer, between 0 and 1 +minBackBufferMemoryReservePercent | number | The percentage of available app memory at which during startup the back buffer will be disabled, between 0 and 1 +minBufferMemoryReservePercent | number | The percentage of available app memory to keep in reserve that prevents buffer from using it, between 0 and 1 This prop should only be set when you are setting the source, changing it after the media is loaded will cause it to be reloaded. diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java index eb4dfa8d..5dcb5e0d 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -113,6 +113,8 @@ class ReactExoplayerView extends FrameLayout implements DrmSessionEventListener { public static final double DEFAULT_MAX_HEAP_ALLOCATION_PERCENT = 1; + public static final double DEFAULT_MIN_BACK_BUFFER_MEMORY_RESERVE = 0; + public static final double DEFAULT_MIN_BUFFER_MEMORY_RESERVE = 0; private static final String TAG = "ReactExoplayerView"; @@ -161,7 +163,8 @@ class ReactExoplayerView extends FrameLayout implements private int bufferForPlaybackMs = DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS; private int bufferForPlaybackAfterRebufferMs = DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS; private double maxHeapAllocationPercent = ReactExoplayerView.DEFAULT_MAX_HEAP_ALLOCATION_PERCENT; - + private double minBackBufferMemoryReservePercent = ReactExoplayerView.DEFAULT_MIN_BACK_BUFFER_MEMORY_RESERVE; + private double minBufferMemoryReservePercent = ReactExoplayerView.DEFAULT_MIN_BUFFER_MEMORY_RESERVE; private Handler mainHandler; private Timer bufferCheckTimer; @@ -449,6 +452,14 @@ class ReactExoplayerView extends FrameLayout implements if (isHeapReached) { return false; } + long usedMemory = runtime.totalMemory() - runtime.freeMemory(); + long freeMemory = runtime.maxMemory() - usedMemory; + long reserveMemory = (long)minBufferMemoryReservePercent * runtime.maxMemory(); + long bufferedMs = bufferedDurationUs / (long)1000; + if (reserveMemory > freeMemory && bufferedMs > 2000) { + // We don't have enough memory in reserve so we stop buffering to allow other components to use it instead + return false; + } if (runtime.freeMemory() == 0) { Log.w("ExoPlayer Warning", "Free memory reached 0, forcing garbage collection"); runtime.gc(); @@ -1622,6 +1633,16 @@ class ReactExoplayerView extends FrameLayout implements } public void setBackBufferDurationMs(int backBufferDurationMs) { + Runtime runtime = Runtime.getRuntime(); + long usedMemory = runtime.totalMemory() - runtime.freeMemory(); + long freeMemory = runtime.maxMemory() - usedMemory; + long reserveMemory = (long)minBackBufferMemoryReservePercent * runtime.maxMemory(); + if (reserveMemory > freeMemory) { + // We don't have enough memory in reserve so we will + Log.w("ExoPlayer Warning", "Not enough reserve memory, setting back buffer to 0ms to reduce memory pressure!"); + this.backBufferDurationMs = 0; + return; + } this.backBufferDurationMs = backBufferDurationMs; } @@ -1679,12 +1700,14 @@ class ReactExoplayerView extends FrameLayout implements exoPlayerView.setHideShutterView(hideShutterView); } - public void setBufferConfig(int newMinBufferMs, int newMaxBufferMs, int newBufferForPlaybackMs, int newBufferForPlaybackAfterRebufferMs, double newMaxHeapAllocationPercent) { + public void setBufferConfig(int newMinBufferMs, int newMaxBufferMs, int newBufferForPlaybackMs, int newBufferForPlaybackAfterRebufferMs, double newMaxHeapAllocationPercent, double newMinBackBufferMemoryReservePercent, double newMinBufferMemoryReservePercent) { minBufferMs = newMinBufferMs; maxBufferMs = newMaxBufferMs; bufferForPlaybackMs = newBufferForPlaybackMs; bufferForPlaybackAfterRebufferMs = newBufferForPlaybackAfterRebufferMs; maxHeapAllocationPercent = newMaxHeapAllocationPercent; + minBackBufferMemoryReservePercent = newMinBackBufferMemoryReservePercent; + minBufferMemoryReservePercent = newMinBufferMemoryReservePercent; releasePlayer(); initializePlayer(); } diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java index a923e050..5d8a84d4 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java @@ -56,6 +56,8 @@ public class ReactExoplayerViewManager extends ViewGroupManager