Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ExoPlayer 2.17.1 update and MediaSource management rework #8020

Merged
merged 5 commits into from
Apr 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ ext {
androidxRoomVersion = '2.4.2'

icepickVersion = '3.2.0'
exoPlayerVersion = '2.14.2'
exoPlayerVersion = '2.17.1'
googleAutoServiceVersion = '1.0.1'
groupieVersion = '2.10.0'
markwonVersion = '4.6.2'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
import androidx.core.content.ContextCompat;
import androidx.preference.PreferenceManager;

import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
Expand Down Expand Up @@ -1884,9 +1884,8 @@ public void onMetadataUpdate(final StreamInfo info, final PlayQueue queue) {
}

@Override
public void onPlayerError(final ExoPlaybackException error) {
if (error.type == ExoPlaybackException.TYPE_SOURCE
|| error.type == ExoPlaybackException.TYPE_UNEXPECTED) {
public void onPlayerError(final PlaybackException error, final boolean isCatchableException) {
if (!isCatchableException) {
// Properly exit from fullscreen
toggleFullscreenIfInFullscreenMode();
hideMainPlayerOnLoadingNewStream();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.PlaybackException;

import org.schabi.newpipe.R;
import org.schabi.newpipe.databinding.ListRadioIconItemBinding;
Expand All @@ -28,6 +29,10 @@
import java.util.Map;
import java.util.function.Supplier;

import static com.google.android.exoplayer2.PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW;
import static com.google.android.exoplayer2.PlaybackException.ERROR_CODE_DECODING_FAILED;
import static com.google.android.exoplayer2.PlaybackException.ERROR_CODE_UNSPECIFIED;

/**
* Outsourced logic for crashing the player in the {@link VideoDetailFragment}.
*/
Expand All @@ -51,7 +56,8 @@ private static Map<String, Supplier<ExoPlaybackException>> getExceptionTypes() {
exceptionTypes.put(
"Source",
() -> ExoPlaybackException.createForSource(
new IOException(defaultMsg)
new IOException(defaultMsg),
ERROR_CODE_BEHIND_LIVE_WINDOW
)
);
exceptionTypes.put(
Expand All @@ -61,13 +67,16 @@ private static Map<String, Supplier<ExoPlaybackException>> getExceptionTypes() {
"Dummy renderer",
0,
null,
C.FORMAT_HANDLED
C.FORMAT_HANDLED,
/*isRecoverable=*/false,
ERROR_CODE_DECODING_FAILED
)
);
exceptionTypes.put(
"Unexpected",
() -> ExoPlaybackException.createForUnexpected(
new RuntimeException(defaultMsg)
new RuntimeException(defaultMsg),
ERROR_CODE_UNSPECIFIED
)
);
exceptionTypes.put(
Expand Down Expand Up @@ -139,7 +148,7 @@ public static void onCrashThePlayer(

/**
* Note that this method does not crash the underlying exoplayer directly (it's not possible).
* It simply supplies a Exception to {@link Player#onPlayerError(ExoPlaybackException)}.
* It simply supplies a Exception to {@link Player#onPlayerError(PlaybackException)}.
* @param player
* @param exception
*/
Expand Down
473 changes: 248 additions & 225 deletions app/src/main/java/org/schabi/newpipe/player/Player.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package org.schabi.newpipe.player.event;

import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.PlaybackException;

public interface PlayerServiceEventListener extends PlayerEventListener {
void onFullscreenStateChanged(boolean fullscreen);
Expand All @@ -9,7 +9,7 @@ public interface PlayerServiceEventListener extends PlayerEventListener {

void onMoreOptionsLongClicked();

void onPlayerError(ExoPlaybackException error);
void onPlayerError(PlaybackException error, boolean isCatchableException);

void hideSystemUiIfNeeded();
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import androidx.media.AudioFocusRequestCompat;
import androidx.media.AudioManagerCompat;

import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.analytics.AnalyticsListener;

public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, AnalyticsListener {
Expand All @@ -27,14 +27,14 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, An
private static final int FOCUS_GAIN_TYPE = AudioManagerCompat.AUDIOFOCUS_GAIN;
private static final int STREAM_TYPE = AudioManager.STREAM_MUSIC;

private final SimpleExoPlayer player;
private final ExoPlayer player;
private final Context context;
private final AudioManager audioManager;

private final AudioFocusRequestCompat request;

public AudioReactor(@NonNull final Context context,
@NonNull final SimpleExoPlayer player) {
@NonNull final ExoPlayer player) {
this.player = player;
this.context = context;
this.audioManager = ContextCompat.getSystemService(context, AudioManager.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@
import android.content.Context;
import android.util.Log;

import androidx.annotation.NonNull;

import com.google.android.exoplayer2.database.ExoDatabaseProvider;
import com.google.android.exoplayer2.database.StandaloneDatabaseProvider;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultDataSource;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource;
import com.google.android.exoplayer2.upstream.FileDataSource;
import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.upstream.cache.CacheDataSink;
Expand All @@ -18,14 +16,16 @@

import java.io.File;

import androidx.annotation.NonNull;

/* package-private */ class CacheFactory implements DataSource.Factory {
private static final String TAG = "CacheFactory";

private static final String CACHE_FOLDER_NAME = "exoplayer";
private static final int CACHE_FLAGS = CacheDataSource.FLAG_BLOCK_ON_CACHE
| CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR;

private final DefaultDataSourceFactory dataSourceFactory;
private final DataSource.Factory dataSourceFactory;
private final File cacheDir;
private final long maxFileSize;

Expand All @@ -49,7 +49,9 @@ private CacheFactory(@NonNull final Context context,
final long maxFileSize) {
this.maxFileSize = maxFileSize;

dataSourceFactory = new DefaultDataSourceFactory(context, userAgent, transferListener);
karyogamy marked this conversation as resolved.
Show resolved Hide resolved
dataSourceFactory = new DefaultDataSource
.Factory(context, new DefaultHttpDataSource.Factory().setUserAgent(userAgent))
.setTransferListener(transferListener);
cacheDir = new File(context.getExternalCacheDir(), CACHE_FOLDER_NAME);
if (!cacheDir.exists()) {
//noinspection ResultOfMethodCallIgnored
Expand All @@ -59,7 +61,7 @@ private CacheFactory(@NonNull final Context context,
if (cache == null) {
final LeastRecentlyUsedCacheEvictor evictor
= new LeastRecentlyUsedCacheEvictor(maxCacheSize);
cache = new SimpleCache(cacheDir, evictor, new ExoDatabaseProvider(context));
cache = new SimpleCache(cacheDir, evictor, new StandaloneDatabaseProvider(context));
}
}

Expand All @@ -68,7 +70,7 @@ private CacheFactory(@NonNull final Context context,
public DataSource createDataSource() {
Log.d(TAG, "initExoPlayerCache: cacheDir = " + cacheDir.getAbsolutePath());

final DefaultDataSource dataSource = dataSourceFactory.createDataSource();
final DataSource dataSource = dataSourceFactory.createDataSource();
final FileDataSource fileSource = new FileDataSource();
final CacheDataSink dataSink = new CacheDataSink(cache, maxFileSize);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import org.schabi.newpipe.MainActivity;
import org.schabi.newpipe.player.mediasession.MediaSessionCallback;
import org.schabi.newpipe.player.mediasession.PlayQueueNavigator;
import org.schabi.newpipe.player.mediasession.PlayQueuePlaybackController;
karyogamy marked this conversation as resolved.
Show resolved Hide resolved

import java.util.Optional;

Expand Down Expand Up @@ -55,7 +54,6 @@ public MediaSessionManager(@NonNull final Context context,
.build());

sessionConnector = new MediaSessionConnector(mediaSession);
sessionConnector.setControlDispatcher(new PlayQueuePlaybackController(callback));
sessionConnector.setQueueNavigator(new PlayQueueNavigator(mediaSession, callback));
sessionConnector.setPlayer(player);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

import android.content.Context;

import androidx.annotation.NonNull;

import com.google.android.exoplayer2.source.ProgressiveMediaSource;
import com.google.android.exoplayer2.source.SingleSampleMediaSource;
import com.google.android.exoplayer2.source.dash.DashMediaSource;
Expand All @@ -13,10 +11,13 @@
import com.google.android.exoplayer2.source.smoothstreaming.DefaultSsChunkSource;
import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.upstream.DefaultDataSource;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource;
import com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy;
import com.google.android.exoplayer2.upstream.TransferListener;

import androidx.annotation.NonNull;

public class PlayerDataSource {

public static final int LIVE_STREAM_EDGE_GAP_MILLIS = 10000;
Expand All @@ -35,12 +36,14 @@ public class PlayerDataSource {
private final DataSource.Factory cacheDataSourceFactory;
private final DataSource.Factory cachelessDataSourceFactory;

public PlayerDataSource(@NonNull final Context context, @NonNull final String userAgent,
public PlayerDataSource(@NonNull final Context context,
@NonNull final String userAgent,
@NonNull final TransferListener transferListener) {
continueLoadingCheckIntervalBytes = PlayerHelper.getProgressiveLoadIntervalBytes(context);
cacheDataSourceFactory = new CacheFactory(context, userAgent, transferListener);
cachelessDataSourceFactory
= new DefaultDataSourceFactory(context, userAgent, transferListener);
cachelessDataSourceFactory = new DefaultDataSource
.Factory(context, new DefaultHttpDataSource.Factory().setUserAgent(userAgent))
.setTransferListener(transferListener);
}

public SsMediaSource.Factory getLiveSsMediaSourceFactory() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;

import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.PlaybackParameters;

import org.schabi.newpipe.App;
Expand Down Expand Up @@ -233,9 +233,10 @@ public void onMoreOptionsLongClicked() {
}

@Override
public void onPlayerError(final ExoPlaybackException error) {
public void onPlayerError(final PlaybackException error,
final boolean isCatchableException) {
if (listener != null) {
listener.onPlayerError(error);
listener.onPlayerError(error, isCatchableException);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package org.schabi.newpipe.player.mediaitem;

import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.StreamType;
import org.schabi.newpipe.player.playqueue.PlayQueueItem;

import java.util.List;
import java.util.Optional;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

/**
* This {@link MediaItemTag} object is designed to contain metadata for a stream
* that has failed to load. It supplies metadata from an underlying
* {@link PlayQueueItem}, which is used by the internal players to resolve actual
* playback info.
*
* This {@link MediaItemTag} does not contain any {@link StreamInfo} that can be
* used to start playback and can be detected by checking {@link ExceptionTag#getErrors()}
* when in generic form.
**/
public final class ExceptionTag implements MediaItemTag {
@NonNull
private final PlayQueueItem item;
@NonNull
private final List<Exception> errors;
@Nullable
private final Object extras;

private ExceptionTag(@NonNull final PlayQueueItem item,
@NonNull final List<Exception> errors,
@Nullable final Object extras) {
this.item = item;
this.errors = errors;
this.extras = extras;
}

public static ExceptionTag of(@NonNull final PlayQueueItem playQueueItem,
@NonNull final List<Exception> errors) {
return new ExceptionTag(playQueueItem, errors, null);
}

@NonNull
@Override
public List<Exception> getErrors() {
return errors;
}

@Override
public int getServiceId() {
return item.getServiceId();
}

@Override
public String getTitle() {
return item.getTitle();
}

@Override
public String getUploaderName() {
return item.getUploader();
}

@Override
public long getDurationSeconds() {
return item.getDuration();
}

@Override
public String getStreamUrl() {
return item.getUrl();
}

@Override
public String getThumbnailUrl() {
return item.getThumbnailUrl();
}

@Override
public String getUploaderUrl() {
return item.getUploaderUrl();
}

@Override
public StreamType getStreamType() {
return item.getStreamType();
}

@Override
public <T> Optional<T> getMaybeExtras(@NonNull final Class<T> type) {
return Optional.ofNullable(extras).map(type::cast);
}

@Override
public <T> MediaItemTag withExtras(@NonNull final T extra) {
return new ExceptionTag(item, errors, extra);
}
}
Loading