VEX-6030: Reduce buffer size based on heap (#13)
This PR changes the behavior on old devices that have poor memory management. Jira: VEX-6030 https://jira.tenkasu.net/browse/VEX-6030 The solution implied customizing the method shouldContinueLoading from RNVLoadControl to use only the available heap, performing tests on an old Nexus 5 it was determined the ideal bytes allocation to half the reported heap, that provided some buffering during ads but smooth playback during the video with no crashes (23:39 of 23:39 at the moment of writing this, video kept playing as expected after 3 ad breaks) The fix is only targeting Marshmallow as the reduction of buffer is substantial and other versions that work properly should not get affected. Depending on the test result of VEX-5758, this same fix can be applied to Nougat Reviews Major reviewer (domain expert): @armadilio3 Minor reviewer: @nickfujita
This commit is contained in:
commit
292b53916a
@ -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.
|
||||
|
||||
|
1
Video.js
1
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,
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
||||
private static final String PROP_BUFFER_CONFIG_MAX_BUFFER_MS = "maxBufferMs";
|
||||
private static final String PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_MS = "bufferForPlaybackMs";
|
||||
private static final String PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS = "bufferForPlaybackAfterRebufferMs";
|
||||
private static final String PROP_BUFFER_CONFIG_MAX_HEAP_ALLOCATION_PERCENT = "maxHeapAllocationPercent";
|
||||
private static final String PROP_PREVENTS_DISPLAY_SLEEP_DURING_VIDEO_PLAYBACK = "preventsDisplaySleepDuringVideoPlayback";
|
||||
private static final String PROP_PROGRESS_UPDATE_INTERVAL = "progressUpdateInterval";
|
||||
private static final String PROP_REPORT_BANDWIDTH = "reportBandwidth";
|
||||
@ -344,6 +345,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
||||
int maxBufferMs = DefaultLoadControl.DEFAULT_MAX_BUFFER_MS;
|
||||
int bufferForPlaybackMs = DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS;
|
||||
int bufferForPlaybackAfterRebufferMs = DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS;
|
||||
double maxHeapAllocationPercent = ReactExoplayerView.DEFAULT_MAX_HEAP_ALLOCATION_PERCENT;
|
||||
if (bufferConfig != null) {
|
||||
minBufferMs = bufferConfig.hasKey(PROP_BUFFER_CONFIG_MIN_BUFFER_MS)
|
||||
? bufferConfig.getInt(PROP_BUFFER_CONFIG_MIN_BUFFER_MS) : minBufferMs;
|
||||
@ -353,7 +355,9 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
||||
? bufferConfig.getInt(PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_MS) : bufferForPlaybackMs;
|
||||
bufferForPlaybackAfterRebufferMs = bufferConfig.hasKey(PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS)
|
||||
? bufferConfig.getInt(PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS) : bufferForPlaybackAfterRebufferMs;
|
||||
videoView.setBufferConfig(minBufferMs, maxBufferMs, bufferForPlaybackMs, bufferForPlaybackAfterRebufferMs);
|
||||
maxHeapAllocationPercent = bufferConfig.hasKey(PROP_BUFFER_CONFIG_MAX_HEAP_ALLOCATION_PERCENT)
|
||||
? bufferConfig.getDouble(PROP_BUFFER_CONFIG_MAX_HEAP_ALLOCATION_PERCENT) : maxHeapAllocationPercent;
|
||||
videoView.setBufferConfig(minBufferMs, maxBufferMs, bufferForPlaybackMs, bufferForPlaybackAfterRebufferMs, maxHeapAllocationPercent);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user