Skip to content

Commit e865c43

Browse files
authored
Merge pull request #7661 from TiA4f8R/livestreams-improvements
Increase playlist stuck target duration coefficient and catch BehindLiveWindowExceptions properly
2 parents 9e5b9ca + 52cc4a0 commit e865c43

2 files changed

Lines changed: 63 additions & 22 deletions

File tree

app/src/main/java/org/schabi/newpipe/player/Player.java

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2517,23 +2517,11 @@ public void onPlayerError(@NonNull final ExoPlaybackException error) {
25172517
Log.e(TAG, "ExoPlayer - onPlayerError() called with:", error);
25182518

25192519
saveStreamProgressState();
2520-
2521-
// create error notification
2522-
final ErrorInfo errorInfo;
2523-
if (currentMetadata == null) {
2524-
errorInfo = new ErrorInfo(error, UserAction.PLAY_STREAM,
2525-
"Player error[type=" + error.type + "] occurred, currentMetadata is null");
2526-
} else {
2527-
errorInfo = new ErrorInfo(error, UserAction.PLAY_STREAM,
2528-
"Player error[type=" + error.type + "] occurred while playing "
2529-
+ currentMetadata.getMetadata().getUrl(),
2530-
currentMetadata.getMetadata());
2531-
}
2532-
ErrorUtil.createNotification(context, errorInfo);
2520+
boolean isCatchableException = false;
25332521

25342522
switch (error.type) {
25352523
case ExoPlaybackException.TYPE_SOURCE:
2536-
processSourceError(error.getSourceException());
2524+
isCatchableException = processSourceError(error.getSourceException());
25372525
break;
25382526
case ExoPlaybackException.TYPE_UNEXPECTED:
25392527
setRecovery();
@@ -2546,22 +2534,60 @@ public void onPlayerError(@NonNull final ExoPlaybackException error) {
25462534
break;
25472535
}
25482536

2537+
if (isCatchableException) {
2538+
return;
2539+
}
2540+
2541+
createErrorNotification(error);
2542+
25492543
if (fragmentListener != null) {
25502544
fragmentListener.onPlayerError(error);
25512545
}
25522546
}
25532547

2554-
private void processSourceError(final IOException error) {
2548+
private void createErrorNotification(@NonNull final ExoPlaybackException error) {
2549+
final ErrorInfo errorInfo;
2550+
if (currentMetadata == null) {
2551+
errorInfo = new ErrorInfo(error, UserAction.PLAY_STREAM,
2552+
"Player error[type=" + error.type + "] occurred, currentMetadata is null");
2553+
} else {
2554+
errorInfo = new ErrorInfo(error, UserAction.PLAY_STREAM,
2555+
"Player error[type=" + error.type + "] occurred while playing "
2556+
+ currentMetadata.getMetadata().getUrl(),
2557+
currentMetadata.getMetadata());
2558+
}
2559+
ErrorUtil.createNotification(context, errorInfo);
2560+
}
2561+
2562+
/**
2563+
* Process an {@link IOException} returned by {@link ExoPlaybackException#getSourceException()}
2564+
* for {@link ExoPlaybackException#TYPE_SOURCE} exceptions.
2565+
*
2566+
* <p>
2567+
* This method sets the recovery position and sends an error message to the play queue if the
2568+
* exception is not a {@link BehindLiveWindowException}.
2569+
* </p>
2570+
* @param error the source error which was thrown by ExoPlayer
2571+
* @return whether the exception thrown is a {@link BehindLiveWindowException} ({@code false}
2572+
* is always returned if ExoPlayer or the play queue is null)
2573+
*/
2574+
private boolean processSourceError(final IOException error) {
25552575
if (exoPlayerIsNull() || playQueue == null) {
2556-
return;
2576+
return false;
25572577
}
2578+
25582579
setRecovery();
25592580

25602581
if (error instanceof BehindLiveWindowException) {
2561-
reloadPlayQueueManager();
2562-
} else {
2563-
playQueue.error();
2582+
simpleExoPlayer.seekToDefaultPosition();
2583+
simpleExoPlayer.prepare();
2584+
// Inform the user that we are reloading the stream by switching to the buffering state
2585+
onBuffering();
2586+
return true;
25642587
}
2588+
2589+
playQueue.error();
2590+
return false;
25652591
}
25662592
//endregion
25672593

app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.google.android.exoplayer2.source.dash.DashMediaSource;
1010
import com.google.android.exoplayer2.source.dash.DefaultDashChunkSource;
1111
import com.google.android.exoplayer2.source.hls.HlsMediaSource;
12+
import com.google.android.exoplayer2.source.hls.playlist.DefaultHlsPlaylistTracker;
1213
import com.google.android.exoplayer2.source.smoothstreaming.DefaultSsChunkSource;
1314
import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource;
1415
import com.google.android.exoplayer2.upstream.DataSource;
@@ -17,9 +18,18 @@
1718
import com.google.android.exoplayer2.upstream.TransferListener;
1819

1920
public class PlayerDataSource {
21+
22+
public static final int LIVE_STREAM_EDGE_GAP_MILLIS = 10000;
23+
24+
/**
25+
* An approximately 4.3 times greater value than the
26+
* {@link DefaultHlsPlaylistTracker#DEFAULT_PLAYLIST_STUCK_TARGET_DURATION_COEFFICIENT default}
27+
* to ensure that (very) low latency livestreams which got stuck for a moment don't crash too
28+
* early.
29+
*/
30+
private static final double PLAYLIST_STUCK_TARGET_DURATION_COEFFICIENT = 15;
2031
private static final int MANIFEST_MINIMUM_RETRY = 5;
2132
private static final int EXTRACTOR_MINIMUM_RETRY = Integer.MAX_VALUE;
22-
public static final int LIVE_STREAM_EDGE_GAP_MILLIS = 10000;
2333

2434
private final DataSource.Factory cacheDataSourceFactory;
2535
private final DataSource.Factory cachelessDataSourceFactory;
@@ -44,8 +54,13 @@ public SsMediaSource.Factory getLiveSsMediaSourceFactory() {
4454
public HlsMediaSource.Factory getLiveHlsMediaSourceFactory() {
4555
return new HlsMediaSource.Factory(cachelessDataSourceFactory)
4656
.setAllowChunklessPreparation(true)
47-
.setLoadErrorHandlingPolicy(
48-
new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY));
57+
.setLoadErrorHandlingPolicy(new DefaultLoadErrorHandlingPolicy(
58+
MANIFEST_MINIMUM_RETRY))
59+
.setPlaylistTrackerFactory((dataSourceFactory, loadErrorHandlingPolicy,
60+
playlistParserFactory) ->
61+
new DefaultHlsPlaylistTracker(dataSourceFactory, loadErrorHandlingPolicy,
62+
playlistParserFactory, PLAYLIST_STUCK_TARGET_DURATION_COEFFICIENT)
63+
);
4964
}
5065

5166
public DashMediaSource.Factory getLiveDashMediaSourceFactory() {

0 commit comments

Comments
 (0)