diff --git a/app/build.gradle b/app/build.gradle index 496533c41..5fc38b85a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -105,7 +105,7 @@ ext { androidxWorkVersion = '2.7.1' icepickVersion = '3.2.0' - exoPlayerVersion = '2.17.1' + exoPlayerVersion = '2.18.0' googleAutoServiceVersion = '1.0.1' groupieVersion = '2.10.1' markwonVersion = '4.6.2' diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index b3194afe6..bae88d07c 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -116,7 +116,6 @@ import androidx.appcompat.content.res.AppCompatResources; import androidx.appcompat.view.ContextThemeWrapper; import androidx.appcompat.widget.AppCompatImageButton; import androidx.appcompat.widget.PopupMenu; -import androidx.collection.ArraySet; import androidx.core.content.ContextCompat; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; @@ -135,9 +134,9 @@ import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.Player.PositionInfo; import com.google.android.exoplayer2.RenderersFactory; import com.google.android.exoplayer2.Timeline; -import com.google.android.exoplayer2.TracksInfo; +import com.google.android.exoplayer2.Tracks; import com.google.android.exoplayer2.source.MediaSource; -import com.google.android.exoplayer2.text.Cue; +import com.google.android.exoplayer2.text.CueGroup; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.trackselection.MappingTrackSelector; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; @@ -513,6 +512,7 @@ public final class Player implements simpleExoPlayer = new ExoPlayer.Builder(context, renderFactory) .setTrackSelector(trackSelector) .setLoadControl(loadController) + .setUsePlatformDiagnostics(false) .build(); simpleExoPlayer.addListener(this); simpleExoPlayer.setPlayWhenReady(playOnReady); @@ -2515,12 +2515,12 @@ public final class Player implements } @Override - public void onTracksInfoChanged(@NonNull final TracksInfo tracksInfo) { + public void onTracksChanged(@NonNull final Tracks tracks) { if (DEBUG) { Log.d(TAG, "ExoPlayer - onTracksChanged(), " - + "track group size = " + tracksInfo.getTrackGroupInfos().size()); + + "track group size = " + tracks.getGroups().size()); } - onTextTracksChanged(tracksInfo); + onTextTracksChanged(tracks); } @Override @@ -2586,8 +2586,8 @@ public final class Player implements } @Override - public void onCues(@NonNull final List cues) { - binding.subtitleView.onCues(cues); + public void onCues(@NonNull final CueGroup cueGroup) { + binding.subtitleView.setCues(cueGroup.cues); } //endregion @@ -3674,34 +3674,35 @@ public final class Player implements binding.subtitleView.setStyle(captionStyle); } - private void onTextTracksChanged(@NonNull final TracksInfo currentTrackInfo) { + private void onTextTracksChanged(@NonNull final Tracks currentTrack) { if (binding == null) { return; } - if (trackSelector.getCurrentMappedTrackInfo() == null - || !currentTrackInfo.isTypeSupportedOrEmpty(C.TRACK_TYPE_TEXT)) { + final boolean trackTypeTextSupported = !currentTrack.containsType(C.TRACK_TYPE_TEXT) + || currentTrack.isTypeSupported(C.TRACK_TYPE_TEXT, false); + if (trackSelector.getCurrentMappedTrackInfo() == null || !trackTypeTextSupported) { binding.captionTextView.setVisibility(View.GONE); return; } // Extract all loaded languages - final List textTracks = currentTrackInfo - .getTrackGroupInfos() + final List textTracks = currentTrack + .getGroups() .stream() - .filter(trackGroupInfo -> C.TRACK_TYPE_TEXT == trackGroupInfo.getTrackType()) + .filter(trackGroupInfo -> C.TRACK_TYPE_TEXT == trackGroupInfo.getType()) .collect(Collectors.toList()); final List availableLanguages = textTracks.stream() - .map(TracksInfo.TrackGroupInfo::getTrackGroup) + .map(Tracks.Group::getMediaTrackGroup) .filter(textTrack -> textTrack.length > 0) .map(textTrack -> textTrack.getFormat(0).language) .collect(Collectors.toList()); // Find selected text track final Optional selectedTracks = textTracks.stream() - .filter(TracksInfo.TrackGroupInfo::isSelected) - .filter(info -> info.getTrackGroup().length >= 1) - .map(info -> info.getTrackGroup().getFormat(0)) + .filter(Tracks.Group::isSelected) + .filter(info -> info.getMediaTrackGroup().length >= 1) + .map(info -> info.getMediaTrackGroup().getFormat(0)) .findFirst(); // Build UI @@ -4249,20 +4250,12 @@ public final class Player implements return; } - final DefaultTrackSelector.ParametersBuilder parametersBuilder = + final DefaultTrackSelector.Parameters.Builder parametersBuilder = trackSelector.buildUponParameters(); - if (videoEnabled) { - // Enable again the video track and the subtitles, if there is one selected - parametersBuilder.setDisabledTrackTypes(Collections.emptySet()); - } else { - // Disable the video track and the ability to select subtitles - // Use an ArraySet because we can't use Set.of() on all supported APIs by the app - final ArraySet disabledTracks = new ArraySet<>(); - disabledTracks.add(C.TRACK_TYPE_TEXT); - disabledTracks.add(C.TRACK_TYPE_VIDEO); - parametersBuilder.setDisabledTrackTypes(disabledTracks); - } + // Enable/disable the video track and the ability to select subtitles + parametersBuilder.setTrackTypeDisabled(C.TRACK_TYPE_TEXT, !videoEnabled); + parametersBuilder.setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, !videoEnabled); trackSelector.setParameters(parametersBuilder); } diff --git a/app/src/main/java/org/schabi/newpipe/player/datasource/YoutubeHttpDataSource.java b/app/src/main/java/org/schabi/newpipe/player/datasource/YoutubeHttpDataSource.java index c9abe65f6..2eecddf36 100644 --- a/app/src/main/java/org/schabi/newpipe/player/datasource/YoutubeHttpDataSource.java +++ b/app/src/main/java/org/schabi/newpipe/player/datasource/YoutubeHttpDataSource.java @@ -1,5 +1,5 @@ /* - * Based on ExoPlayer's DefaultHttpDataSource, version 2.17.1. + * Based on ExoPlayer's DefaultHttpDataSource, version 2.18.0. * * Original source code copyright (C) 2016 The Android Open Source Project, licensed under the * Apache License, Version 2.0. diff --git a/app/src/main/java/org/schabi/newpipe/player/mediaitem/MediaItemTag.java b/app/src/main/java/org/schabi/newpipe/player/mediaitem/MediaItemTag.java index f84b0383a..d23dd4574 100644 --- a/app/src/main/java/org/schabi/newpipe/player/mediaitem/MediaItemTag.java +++ b/app/src/main/java/org/schabi/newpipe/player/mediaitem/MediaItemTag.java @@ -3,6 +3,7 @@ package org.schabi.newpipe.player.mediaitem; import android.net.Uri; import com.google.android.exoplayer2.MediaItem; +import com.google.android.exoplayer2.MediaItem.RequestMetadata; import com.google.android.exoplayer2.MediaMetadata; import com.google.android.exoplayer2.Player; @@ -76,7 +77,6 @@ public interface MediaItemTag { @NonNull default MediaItem asMediaItem() { final MediaMetadata mediaMetadata = new MediaMetadata.Builder() - .setMediaUri(Uri.parse(getStreamUrl())) .setArtworkUri(Uri.parse(getThumbnailUrl())) .setArtist(getUploaderName()) .setDescription(getTitle()) @@ -84,10 +84,15 @@ public interface MediaItemTag { .setTitle(getTitle()) .build(); + final RequestMetadata requestMetaData = new RequestMetadata.Builder() + .setMediaUri(Uri.parse(getStreamUrl())) + .build(); + return MediaItem.fromUri(getStreamUrl()) .buildUpon() .setMediaId(makeMediaId()) .setMediaMetadata(mediaMetadata) + .setRequestMetadata(requestMetaData) .setTag(this) .build(); } diff --git a/app/src/main/java/org/schabi/newpipe/player/playback/SurfaceHolderCallback.java b/app/src/main/java/org/schabi/newpipe/player/playback/SurfaceHolderCallback.java index 5d67e6967..da6cb36d4 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playback/SurfaceHolderCallback.java +++ b/app/src/main/java/org/schabi/newpipe/player/playback/SurfaceHolderCallback.java @@ -4,7 +4,7 @@ import android.content.Context; import android.view.SurfaceHolder; import com.google.android.exoplayer2.Player; -import com.google.android.exoplayer2.video.DummySurface; +import com.google.android.exoplayer2.video.PlaceholderSurface; /** * Prevent error message: 'Unrecoverable player error occurred' @@ -26,7 +26,7 @@ public final class SurfaceHolderCallback implements SurfaceHolder.Callback { private final Context context; private final Player player; - private DummySurface dummySurface; + private PlaceholderSurface placeholderSurface; public SurfaceHolderCallback(final Context context, final Player player) { this.context = context; @@ -47,16 +47,16 @@ public final class SurfaceHolderCallback implements SurfaceHolder.Callback { @Override public void surfaceDestroyed(final SurfaceHolder holder) { - if (dummySurface == null) { - dummySurface = DummySurface.newInstanceV17(context, false); + if (placeholderSurface == null) { + placeholderSurface = PlaceholderSurface.newInstanceV17(context, false); } - player.setVideoSurface(dummySurface); + player.setVideoSurface(placeholderSurface); } public void release() { - if (dummySurface != null) { - dummySurface.release(); - dummySurface = null; + if (placeholderSurface != null) { + placeholderSurface.release(); + placeholderSurface = null; } } } diff --git a/app/src/main/java/org/schabi/newpipe/player/resolver/PlaybackResolver.java b/app/src/main/java/org/schabi/newpipe/player/resolver/PlaybackResolver.java index 34e7e9bd1..ead127250 100644 --- a/app/src/main/java/org/schabi/newpipe/player/resolver/PlaybackResolver.java +++ b/app/src/main/java/org/schabi/newpipe/player/resolver/PlaybackResolver.java @@ -172,9 +172,10 @@ public interface PlaybackResolver extends Resolver { try { final StreamInfoTag tag = StreamInfoTag.of(info); if (!info.getHlsUrl().isEmpty()) { - return buildLiveMediaSource(dataSource, info.getHlsUrl(), C.TYPE_HLS, tag); + return buildLiveMediaSource(dataSource, info.getHlsUrl(), C.CONTENT_TYPE_HLS, tag); } else if (!info.getDashMpdUrl().isEmpty()) { - return buildLiveMediaSource(dataSource, info.getDashMpdUrl(), C.TYPE_DASH, tag); + return buildLiveMediaSource( + dataSource, info.getDashMpdUrl(), C.CONTENT_TYPE_DASH, tag); } } catch (final Exception e) { Log.w(TAG, "Error when generating live media source, falling back to standard sources", @@ -190,17 +191,17 @@ public interface PlaybackResolver extends Resolver { final MediaItemTag metadata) throws ResolverException { final MediaSource.Factory factory; switch (type) { - case C.TYPE_SS: + case C.CONTENT_TYPE_SS: factory = dataSource.getLiveSsMediaSourceFactory(); break; - case C.TYPE_DASH: + case C.CONTENT_TYPE_DASH: factory = dataSource.getLiveDashMediaSourceFactory(); break; - case C.TYPE_HLS: + case C.CONTENT_TYPE_HLS: factory = dataSource.getLiveHlsMediaSourceFactory(); break; - case C.TYPE_OTHER: - case C.TYPE_RTSP: + case C.CONTENT_TYPE_OTHER: + case C.CONTENT_TYPE_RTSP: default: throw new ResolverException("Unsupported type: " + type); }