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.
|
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.
|
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.
|
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.
|
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,
|
maxBufferMs: PropTypes.number,
|
||||||
bufferForPlaybackMs: PropTypes.number,
|
bufferForPlaybackMs: PropTypes.number,
|
||||||
bufferForPlaybackAfterRebufferMs: PropTypes.number,
|
bufferForPlaybackAfterRebufferMs: PropTypes.number,
|
||||||
|
maxHeapAllocationPercent: PropTypes.number,
|
||||||
}),
|
}),
|
||||||
stereoPan: PropTypes.number,
|
stereoPan: PropTypes.number,
|
||||||
rate: PropTypes.number,
|
rate: PropTypes.number,
|
||||||
|
@ -2,6 +2,7 @@ package com.brentvatne.exoplayer;
|
|||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.app.ActivityManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@ -111,6 +112,8 @@ class ReactExoplayerView extends FrameLayout implements
|
|||||||
MetadataOutput,
|
MetadataOutput,
|
||||||
DrmSessionEventListener {
|
DrmSessionEventListener {
|
||||||
|
|
||||||
|
public static final double DEFAULT_MAX_HEAP_ALLOCATION_PERCENT = 1;
|
||||||
|
|
||||||
private static final String TAG = "ReactExoplayerView";
|
private static final String TAG = "ReactExoplayerView";
|
||||||
|
|
||||||
private static final CookieManager DEFAULT_COOKIE_MANAGER;
|
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 maxBufferMs = DefaultLoadControl.DEFAULT_MAX_BUFFER_MS;
|
||||||
private int bufferForPlaybackMs = DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS;
|
private int bufferForPlaybackMs = DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS;
|
||||||
private int bufferForPlaybackAfterRebufferMs = DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_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 Handler mainHandler;
|
||||||
private Timer bufferCheckTimer;
|
private Timer bufferCheckTimer;
|
||||||
@ -418,6 +422,7 @@ class ReactExoplayerView extends FrameLayout implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class RNVLoadControl extends DefaultLoadControl {
|
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) {
|
public RNVLoadControl(DefaultAllocator allocator, int minBufferMs, int maxBufferMs, int bufferForPlaybackMs, int bufferForPlaybackAfterRebufferMs, int targetBufferBytes, boolean prioritizeTimeOverSizeThresholds, int backBufferDurationMs, boolean retainBackBufferFromKeyframe) {
|
||||||
super(allocator,
|
super(allocator,
|
||||||
minBufferMs,
|
minBufferMs,
|
||||||
@ -428,6 +433,8 @@ class ReactExoplayerView extends FrameLayout implements
|
|||||||
prioritizeTimeOverSizeThresholds,
|
prioritizeTimeOverSizeThresholds,
|
||||||
backBufferDurationMs,
|
backBufferDurationMs,
|
||||||
retainBackBufferFromKeyframe);
|
retainBackBufferFromKeyframe);
|
||||||
|
ActivityManager activityManager = (ActivityManager) themedReactContext.getSystemService(themedReactContext.ACTIVITY_SERVICE);
|
||||||
|
availableHeapInBytes = (int) Math.floor(activityManager.getMemoryClass() * maxHeapAllocationPercent * 1024 * 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -435,6 +442,11 @@ class ReactExoplayerView extends FrameLayout implements
|
|||||||
if (ReactExoplayerView.this.disableBuffering) {
|
if (ReactExoplayerView.this.disableBuffering) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
int loadedBytes = getAllocator().getTotalBytesAllocated();
|
||||||
|
boolean isHeapReached = availableHeapInBytes > 0 && loadedBytes >= availableHeapInBytes;
|
||||||
|
if (isHeapReached) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return super.shouldContinueLoading(playbackPositionUs, bufferedDurationUs, playbackSpeed);
|
return super.shouldContinueLoading(playbackPositionUs, bufferedDurationUs, playbackSpeed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1660,11 +1672,12 @@ class ReactExoplayerView extends FrameLayout implements
|
|||||||
exoPlayerView.setHideShutterView(hideShutterView);
|
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;
|
minBufferMs = newMinBufferMs;
|
||||||
maxBufferMs = newMaxBufferMs;
|
maxBufferMs = newMaxBufferMs;
|
||||||
bufferForPlaybackMs = newBufferForPlaybackMs;
|
bufferForPlaybackMs = newBufferForPlaybackMs;
|
||||||
bufferForPlaybackAfterRebufferMs = newBufferForPlaybackAfterRebufferMs;
|
bufferForPlaybackAfterRebufferMs = newBufferForPlaybackAfterRebufferMs;
|
||||||
|
maxHeapAllocationPercent = newMaxHeapAllocationPercent;
|
||||||
releasePlayer();
|
releasePlayer();
|
||||||
initializePlayer();
|
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_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_MS = "bufferForPlaybackMs";
|
||||||
private static final String PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS = "bufferForPlaybackAfterRebufferMs";
|
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_PREVENTS_DISPLAY_SLEEP_DURING_VIDEO_PLAYBACK = "preventsDisplaySleepDuringVideoPlayback";
|
||||||
private static final String PROP_PROGRESS_UPDATE_INTERVAL = "progressUpdateInterval";
|
private static final String PROP_PROGRESS_UPDATE_INTERVAL = "progressUpdateInterval";
|
||||||
private static final String PROP_REPORT_BANDWIDTH = "reportBandwidth";
|
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 maxBufferMs = DefaultLoadControl.DEFAULT_MAX_BUFFER_MS;
|
||||||
int bufferForPlaybackMs = DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS;
|
int bufferForPlaybackMs = DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS;
|
||||||
int bufferForPlaybackAfterRebufferMs = DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS;
|
int bufferForPlaybackAfterRebufferMs = DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS;
|
||||||
|
double maxHeapAllocationPercent = ReactExoplayerView.DEFAULT_MAX_HEAP_ALLOCATION_PERCENT;
|
||||||
if (bufferConfig != null) {
|
if (bufferConfig != null) {
|
||||||
minBufferMs = bufferConfig.hasKey(PROP_BUFFER_CONFIG_MIN_BUFFER_MS)
|
minBufferMs = bufferConfig.hasKey(PROP_BUFFER_CONFIG_MIN_BUFFER_MS)
|
||||||
? bufferConfig.getInt(PROP_BUFFER_CONFIG_MIN_BUFFER_MS) : minBufferMs;
|
? 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;
|
? bufferConfig.getInt(PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_MS) : bufferForPlaybackMs;
|
||||||
bufferForPlaybackAfterRebufferMs = bufferConfig.hasKey(PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS)
|
bufferForPlaybackAfterRebufferMs = bufferConfig.hasKey(PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS)
|
||||||
? bufferConfig.getInt(PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS) : bufferForPlaybackAfterRebufferMs;
|
? 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…
x
Reference in New Issue
Block a user