diff --git a/README.md b/README.md index ca6745d3..564423f8 100644 --- a/README.md +++ b/README.md @@ -385,6 +385,7 @@ minBufferMs | number | The default minimum duration of media that the player wil maxBufferMs | number | The default maximum duration of media that the player will attempt to buffer, in milliseconds. 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 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/Video.js b/Video.js index fdfa141e..0a97be1d 100644 --- a/Video.js +++ b/Video.js @@ -468,6 +468,7 @@ Video.propTypes = { maxBufferMs: PropTypes.number, bufferForPlaybackMs: PropTypes.number, bufferForPlaybackAfterRebufferMs: PropTypes.number, + maxHeapAllocationPercent: PropTypes.number, }), stereoPan: PropTypes.number, rate: PropTypes.number, 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 7873d95d..ea27b947 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -2,6 +2,7 @@ package com.brentvatne.exoplayer; import android.annotation.SuppressLint; import android.app.Activity; +import android.app.ActivityManager; import android.content.Context; import android.media.AudioManager; import android.net.Uri; @@ -111,6 +112,8 @@ class ReactExoplayerView extends FrameLayout implements MetadataOutput, DrmSessionEventListener { + public static final double DEFAULT_MAX_HEAP_ALLOCATION_PERCENT = 1; + private static final String TAG = "ReactExoplayerView"; private static final CookieManager DEFAULT_COOKIE_MANAGER; @@ -157,6 +160,7 @@ class ReactExoplayerView extends FrameLayout implements private int maxBufferMs = DefaultLoadControl.DEFAULT_MAX_BUFFER_MS; 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 Handler mainHandler; private Timer bufferCheckTimer; @@ -215,7 +219,7 @@ class ReactExoplayerView extends FrameLayout implements public double getPositionInFirstPeriodMsForCurrentWindow(long currentPosition) { Timeline.Window window = new Timeline.Window(); - if(!player.getCurrentTimeline().isEmpty()) { + if(!player.getCurrentTimeline().isEmpty()) { player.getCurrentTimeline().getWindow(player.getCurrentWindowIndex(), window); } return window.windowStartTimeMs + currentPosition; @@ -418,6 +422,7 @@ class ReactExoplayerView extends FrameLayout implements } private class RNVLoadControl extends DefaultLoadControl { + private int availableHeapInBytes = 0; public RNVLoadControl(DefaultAllocator allocator, int minBufferMs, int maxBufferMs, int bufferForPlaybackMs, int bufferForPlaybackAfterRebufferMs, int targetBufferBytes, boolean prioritizeTimeOverSizeThresholds, int backBufferDurationMs, boolean retainBackBufferFromKeyframe) { super(allocator, minBufferMs, @@ -428,6 +433,8 @@ class ReactExoplayerView extends FrameLayout implements prioritizeTimeOverSizeThresholds, backBufferDurationMs, retainBackBufferFromKeyframe); + ActivityManager activityManager = (ActivityManager) themedReactContext.getSystemService(themedReactContext.ACTIVITY_SERVICE); + availableHeapInBytes = (int) Math.floor(activityManager.getMemoryClass() * maxHeapAllocationPercent * 1024 * 1024); } @Override @@ -435,6 +442,11 @@ class ReactExoplayerView extends FrameLayout implements if (ReactExoplayerView.this.disableBuffering) { return false; } + int loadedBytes = getAllocator().getTotalBytesAllocated(); + boolean isHeapReached = availableHeapInBytes > 0 && loadedBytes >= availableHeapInBytes; + if (isHeapReached) { + return false; + } return super.shouldContinueLoading(playbackPositionUs, bufferedDurationUs, playbackSpeed); } } @@ -1660,11 +1672,12 @@ class ReactExoplayerView extends FrameLayout implements exoPlayerView.setHideShutterView(hideShutterView); } - public void setBufferConfig(int newMinBufferMs, int newMaxBufferMs, int newBufferForPlaybackMs, int newBufferForPlaybackAfterRebufferMs) { + public void setBufferConfig(int newMinBufferMs, int newMaxBufferMs, int newBufferForPlaybackMs, int newBufferForPlaybackAfterRebufferMs, double newMaxHeapAllocationPercent) { minBufferMs = newMinBufferMs; maxBufferMs = newMaxBufferMs; bufferForPlaybackMs = newBufferForPlaybackMs; bufferForPlaybackAfterRebufferMs = newBufferForPlaybackAfterRebufferMs; + maxHeapAllocationPercent = newMaxHeapAllocationPercent; 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 0e7a8c66..a923e050 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java @@ -55,6 +55,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager