mirror of
https://github.com/TeamNewPipe/NewPipe.git
synced 2024-11-25 12:32:31 +01:00
Merge pull request #7661 from TiA4f8R/livestreams-improvements
Increase playlist stuck target duration coefficient and catch BehindLiveWindowExceptions properly
This commit is contained in:
commit
e865c4350e
@ -2517,23 +2517,11 @@ public final class Player implements
|
|||||||
Log.e(TAG, "ExoPlayer - onPlayerError() called with:", error);
|
Log.e(TAG, "ExoPlayer - onPlayerError() called with:", error);
|
||||||
|
|
||||||
saveStreamProgressState();
|
saveStreamProgressState();
|
||||||
|
boolean isCatchableException = false;
|
||||||
// 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);
|
|
||||||
|
|
||||||
switch (error.type) {
|
switch (error.type) {
|
||||||
case ExoPlaybackException.TYPE_SOURCE:
|
case ExoPlaybackException.TYPE_SOURCE:
|
||||||
processSourceError(error.getSourceException());
|
isCatchableException = processSourceError(error.getSourceException());
|
||||||
break;
|
break;
|
||||||
case ExoPlaybackException.TYPE_UNEXPECTED:
|
case ExoPlaybackException.TYPE_UNEXPECTED:
|
||||||
setRecovery();
|
setRecovery();
|
||||||
@ -2546,22 +2534,60 @@ public final class Player implements
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isCatchableException) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
createErrorNotification(error);
|
||||||
|
|
||||||
if (fragmentListener != null) {
|
if (fragmentListener != null) {
|
||||||
fragmentListener.onPlayerError(error);
|
fragmentListener.onPlayerError(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processSourceError(final IOException error) {
|
private void createErrorNotification(@NonNull final ExoPlaybackException error) {
|
||||||
if (exoPlayerIsNull() || playQueue == null) {
|
final ErrorInfo errorInfo;
|
||||||
return;
|
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 false;
|
||||||
|
}
|
||||||
|
|
||||||
setRecovery();
|
setRecovery();
|
||||||
|
|
||||||
if (error instanceof BehindLiveWindowException) {
|
if (error instanceof BehindLiveWindowException) {
|
||||||
reloadPlayQueueManager();
|
simpleExoPlayer.seekToDefaultPosition();
|
||||||
} else {
|
simpleExoPlayer.prepare();
|
||||||
playQueue.error();
|
// Inform the user that we are reloading the stream by switching to the buffering state
|
||||||
|
onBuffering();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
playQueue.error();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ import com.google.android.exoplayer2.source.SingleSampleMediaSource;
|
|||||||
import com.google.android.exoplayer2.source.dash.DashMediaSource;
|
import com.google.android.exoplayer2.source.dash.DashMediaSource;
|
||||||
import com.google.android.exoplayer2.source.dash.DefaultDashChunkSource;
|
import com.google.android.exoplayer2.source.dash.DefaultDashChunkSource;
|
||||||
import com.google.android.exoplayer2.source.hls.HlsMediaSource;
|
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.DefaultSsChunkSource;
|
||||||
import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource;
|
import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource;
|
||||||
import com.google.android.exoplayer2.upstream.DataSource;
|
import com.google.android.exoplayer2.upstream.DataSource;
|
||||||
@ -17,9 +18,18 @@ import com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy;
|
|||||||
import com.google.android.exoplayer2.upstream.TransferListener;
|
import com.google.android.exoplayer2.upstream.TransferListener;
|
||||||
|
|
||||||
public class PlayerDataSource {
|
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 MANIFEST_MINIMUM_RETRY = 5;
|
||||||
private static final int EXTRACTOR_MINIMUM_RETRY = Integer.MAX_VALUE;
|
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 cacheDataSourceFactory;
|
||||||
private final DataSource.Factory cachelessDataSourceFactory;
|
private final DataSource.Factory cachelessDataSourceFactory;
|
||||||
@ -44,8 +54,13 @@ public class PlayerDataSource {
|
|||||||
public HlsMediaSource.Factory getLiveHlsMediaSourceFactory() {
|
public HlsMediaSource.Factory getLiveHlsMediaSourceFactory() {
|
||||||
return new HlsMediaSource.Factory(cachelessDataSourceFactory)
|
return new HlsMediaSource.Factory(cachelessDataSourceFactory)
|
||||||
.setAllowChunklessPreparation(true)
|
.setAllowChunklessPreparation(true)
|
||||||
.setLoadErrorHandlingPolicy(
|
.setLoadErrorHandlingPolicy(new DefaultLoadErrorHandlingPolicy(
|
||||||
new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY));
|
MANIFEST_MINIMUM_RETRY))
|
||||||
|
.setPlaylistTrackerFactory((dataSourceFactory, loadErrorHandlingPolicy,
|
||||||
|
playlistParserFactory) ->
|
||||||
|
new DefaultHlsPlaylistTracker(dataSourceFactory, loadErrorHandlingPolicy,
|
||||||
|
playlistParserFactory, PLAYLIST_STUCK_TARGET_DURATION_COEFFICIENT)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DashMediaSource.Factory getLiveDashMediaSourceFactory() {
|
public DashMediaSource.Factory getLiveDashMediaSourceFactory() {
|
||||||
|
Loading…
Reference in New Issue
Block a user