Skip to content

Commit

Permalink
Merge pull request #7661 from TiA4f8R/livestreams-improvements
Browse files Browse the repository at this point in the history
Increase playlist stuck target duration coefficient and catch BehindLiveWindowExceptions properly
  • Loading branch information
Redirion authored Feb 1, 2022
2 parents 9e5b9ca + 52cc4a0 commit e865c43
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 22 deletions.
64 changes: 45 additions & 19 deletions app/src/main/java/org/schabi/newpipe/player/Player.java
Original file line number Diff line number Diff line change
Expand Up @@ -2517,23 +2517,11 @@ public void onPlayerError(@NonNull final ExoPlaybackException error) {
Log.e(TAG, "ExoPlayer - onPlayerError() called with:", error);

saveStreamProgressState();

// create error notification
final ErrorInfo errorInfo;
if (currentMetadata == null) {
errorInfo = new ErrorInfo(error, UserAction.PLAY_STREAM,
"Player error[type=" + error.type + "] occurred, currentMetadata is null");
} else {
errorInfo = new ErrorInfo(error, UserAction.PLAY_STREAM,
"Player error[type=" + error.type + "] occurred while playing "
+ currentMetadata.getMetadata().getUrl(),
currentMetadata.getMetadata());
}
ErrorUtil.createNotification(context, errorInfo);
boolean isCatchableException = false;

switch (error.type) {
case ExoPlaybackException.TYPE_SOURCE:
processSourceError(error.getSourceException());
isCatchableException = processSourceError(error.getSourceException());
break;
case ExoPlaybackException.TYPE_UNEXPECTED:
setRecovery();
Expand All @@ -2546,22 +2534,60 @@ public void onPlayerError(@NonNull final ExoPlaybackException error) {
break;
}

if (isCatchableException) {
return;
}

createErrorNotification(error);

if (fragmentListener != null) {
fragmentListener.onPlayerError(error);
}
}

private void processSourceError(final IOException error) {
private void createErrorNotification(@NonNull final ExoPlaybackException error) {
final ErrorInfo errorInfo;
if (currentMetadata == null) {
errorInfo = new ErrorInfo(error, UserAction.PLAY_STREAM,
"Player error[type=" + error.type + "] occurred, currentMetadata is null");
} else {
errorInfo = new ErrorInfo(error, UserAction.PLAY_STREAM,
"Player error[type=" + error.type + "] occurred while playing "
+ currentMetadata.getMetadata().getUrl(),
currentMetadata.getMetadata());
}
ErrorUtil.createNotification(context, errorInfo);
}

/**
* Process an {@link IOException} returned by {@link ExoPlaybackException#getSourceException()}
* for {@link ExoPlaybackException#TYPE_SOURCE} exceptions.
*
* <p>
* This method sets the recovery position and sends an error message to the play queue if the
* exception is not a {@link BehindLiveWindowException}.
* </p>
* @param error the source error which was thrown by ExoPlayer
* @return whether the exception thrown is a {@link BehindLiveWindowException} ({@code false}
* is always returned if ExoPlayer or the play queue is null)
*/
private boolean processSourceError(final IOException error) {
if (exoPlayerIsNull() || playQueue == null) {
return;
return false;
}

setRecovery();

if (error instanceof BehindLiveWindowException) {
reloadPlayQueueManager();
} else {
playQueue.error();
simpleExoPlayer.seekToDefaultPosition();
simpleExoPlayer.prepare();
// Inform the user that we are reloading the stream by switching to the buffering state
onBuffering();
return true;
}

playQueue.error();
return false;
}
//endregion

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.google.android.exoplayer2.source.dash.DashMediaSource;
import com.google.android.exoplayer2.source.dash.DefaultDashChunkSource;
import com.google.android.exoplayer2.source.hls.HlsMediaSource;
import com.google.android.exoplayer2.source.hls.playlist.DefaultHlsPlaylistTracker;
import com.google.android.exoplayer2.source.smoothstreaming.DefaultSsChunkSource;
import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource;
import com.google.android.exoplayer2.upstream.DataSource;
Expand All @@ -17,9 +18,18 @@
import com.google.android.exoplayer2.upstream.TransferListener;

public class PlayerDataSource {

public static final int LIVE_STREAM_EDGE_GAP_MILLIS = 10000;

/**
* An approximately 4.3 times greater value than the
* {@link DefaultHlsPlaylistTracker#DEFAULT_PLAYLIST_STUCK_TARGET_DURATION_COEFFICIENT default}
* to ensure that (very) low latency livestreams which got stuck for a moment don't crash too
* early.
*/
private static final double PLAYLIST_STUCK_TARGET_DURATION_COEFFICIENT = 15;
private static final int MANIFEST_MINIMUM_RETRY = 5;
private static final int EXTRACTOR_MINIMUM_RETRY = Integer.MAX_VALUE;
public static final int LIVE_STREAM_EDGE_GAP_MILLIS = 10000;

private final DataSource.Factory cacheDataSourceFactory;
private final DataSource.Factory cachelessDataSourceFactory;
Expand All @@ -44,8 +54,13 @@ public SsMediaSource.Factory getLiveSsMediaSourceFactory() {
public HlsMediaSource.Factory getLiveHlsMediaSourceFactory() {
return new HlsMediaSource.Factory(cachelessDataSourceFactory)
.setAllowChunklessPreparation(true)
.setLoadErrorHandlingPolicy(
new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY));
.setLoadErrorHandlingPolicy(new DefaultLoadErrorHandlingPolicy(
MANIFEST_MINIMUM_RETRY))
.setPlaylistTrackerFactory((dataSourceFactory, loadErrorHandlingPolicy,
playlistParserFactory) ->
new DefaultHlsPlaylistTracker(dataSourceFactory, loadErrorHandlingPolicy,
playlistParserFactory, PLAYLIST_STUCK_TARGET_DURATION_COEFFICIENT)
);
}

public DashMediaSource.Factory getLiveDashMediaSourceFactory() {
Expand Down

0 comments on commit e865c43

Please sign in to comment.