Update ExoPlayer to 2.18.0

This commit is contained in:
TacoTheDank 2022-06-25 21:14:42 -04:00
parent d5985be94a
commit 1404581e9b
6 changed files with 46 additions and 48 deletions

View file

@ -105,7 +105,7 @@ ext {
androidxWorkVersion = '2.7.1' androidxWorkVersion = '2.7.1'
icepickVersion = '3.2.0' icepickVersion = '3.2.0'
exoPlayerVersion = '2.17.1' exoPlayerVersion = '2.18.0'
googleAutoServiceVersion = '1.0.1' googleAutoServiceVersion = '1.0.1'
groupieVersion = '2.10.1' groupieVersion = '2.10.1'
markwonVersion = '4.6.2' markwonVersion = '4.6.2'

View file

@ -116,7 +116,6 @@ import androidx.appcompat.content.res.AppCompatResources;
import androidx.appcompat.view.ContextThemeWrapper; import androidx.appcompat.view.ContextThemeWrapper;
import androidx.appcompat.widget.AppCompatImageButton; import androidx.appcompat.widget.AppCompatImageButton;
import androidx.appcompat.widget.PopupMenu; import androidx.appcompat.widget.PopupMenu;
import androidx.collection.ArraySet;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.core.graphics.Insets; import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat; 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.Player.PositionInfo;
import com.google.android.exoplayer2.RenderersFactory; import com.google.android.exoplayer2.RenderersFactory;
import com.google.android.exoplayer2.Timeline; 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.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.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector; import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
@ -2506,12 +2505,12 @@ public final class Player implements
} }
@Override @Override
public void onTracksInfoChanged(@NonNull final TracksInfo tracksInfo) { public void onTracksChanged(@NonNull final Tracks tracks) {
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "ExoPlayer - onTracksChanged(), " Log.d(TAG, "ExoPlayer - onTracksChanged(), "
+ "track group size = " + tracksInfo.getTrackGroupInfos().size()); + "track group size = " + tracks.getGroups().size());
} }
onTextTracksChanged(tracksInfo); onTextTracksChanged(tracks);
} }
@Override @Override
@ -2577,8 +2576,8 @@ public final class Player implements
} }
@Override @Override
public void onCues(@NonNull final List<Cue> cues) { public void onCues(@NonNull final CueGroup cueGroup) {
binding.subtitleView.onCues(cues); binding.subtitleView.setCues(cueGroup.cues);
} }
//endregion //endregion
@ -3665,34 +3664,35 @@ public final class Player implements
binding.subtitleView.setStyle(captionStyle); binding.subtitleView.setStyle(captionStyle);
} }
private void onTextTracksChanged(@NonNull final TracksInfo currentTrackInfo) { private void onTextTracksChanged(@NonNull final Tracks currentTrack) {
if (binding == null) { if (binding == null) {
return; return;
} }
if (trackSelector.getCurrentMappedTrackInfo() == null final boolean trackTypeTextSupported = !currentTrack.containsType(C.TRACK_TYPE_TEXT)
|| !currentTrackInfo.isTypeSupportedOrEmpty(C.TRACK_TYPE_TEXT)) { || currentTrack.isTypeSupported(C.TRACK_TYPE_TEXT, false);
if (trackSelector.getCurrentMappedTrackInfo() == null || !trackTypeTextSupported) {
binding.captionTextView.setVisibility(View.GONE); binding.captionTextView.setVisibility(View.GONE);
return; return;
} }
// Extract all loaded languages // Extract all loaded languages
final List<TracksInfo.TrackGroupInfo> textTracks = currentTrackInfo final List<Tracks.Group> textTracks = currentTrack
.getTrackGroupInfos() .getGroups()
.stream() .stream()
.filter(trackGroupInfo -> C.TRACK_TYPE_TEXT == trackGroupInfo.getTrackType()) .filter(trackGroupInfo -> C.TRACK_TYPE_TEXT == trackGroupInfo.getType())
.collect(Collectors.toList()); .collect(Collectors.toList());
final List<String> availableLanguages = textTracks.stream() final List<String> availableLanguages = textTracks.stream()
.map(TracksInfo.TrackGroupInfo::getTrackGroup) .map(Tracks.Group::getMediaTrackGroup)
.filter(textTrack -> textTrack.length > 0) .filter(textTrack -> textTrack.length > 0)
.map(textTrack -> textTrack.getFormat(0).language) .map(textTrack -> textTrack.getFormat(0).language)
.collect(Collectors.toList()); .collect(Collectors.toList());
// Find selected text track // Find selected text track
final Optional<Format> selectedTracks = textTracks.stream() final Optional<Format> selectedTracks = textTracks.stream()
.filter(TracksInfo.TrackGroupInfo::isSelected) .filter(Tracks.Group::isSelected)
.filter(info -> info.getTrackGroup().length >= 1) .filter(info -> info.getMediaTrackGroup().length >= 1)
.map(info -> info.getTrackGroup().getFormat(0)) .map(info -> info.getMediaTrackGroup().getFormat(0))
.findFirst(); .findFirst();
// Build UI // Build UI
@ -4240,20 +4240,12 @@ public final class Player implements
return; return;
} }
final DefaultTrackSelector.ParametersBuilder parametersBuilder = final DefaultTrackSelector.Parameters.Builder parametersBuilder =
trackSelector.buildUponParameters(); trackSelector.buildUponParameters();
if (videoEnabled) { // Enable/disable the video track and the ability to select subtitles
// Enable again the video track and the subtitles, if there is one selected parametersBuilder.setTrackTypeDisabled(C.TRACK_TYPE_TEXT, !videoEnabled);
parametersBuilder.setDisabledTrackTypes(Collections.emptySet()); parametersBuilder.setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, !videoEnabled);
} 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<Integer> disabledTracks = new ArraySet<>();
disabledTracks.add(C.TRACK_TYPE_TEXT);
disabledTracks.add(C.TRACK_TYPE_VIDEO);
parametersBuilder.setDisabledTrackTypes(disabledTracks);
}
trackSelector.setParameters(parametersBuilder); trackSelector.setParameters(parametersBuilder);
} }

View file

@ -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 * Original source code copyright (C) 2016 The Android Open Source Project, licensed under the
* Apache License, Version 2.0. * Apache License, Version 2.0.

View file

@ -3,6 +3,7 @@ package org.schabi.newpipe.player.mediaitem;
import android.net.Uri; import android.net.Uri;
import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.MediaItem.RequestMetadata;
import com.google.android.exoplayer2.MediaMetadata; import com.google.android.exoplayer2.MediaMetadata;
import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Player;
@ -76,7 +77,6 @@ public interface MediaItemTag {
@NonNull @NonNull
default MediaItem asMediaItem() { default MediaItem asMediaItem() {
final MediaMetadata mediaMetadata = new MediaMetadata.Builder() final MediaMetadata mediaMetadata = new MediaMetadata.Builder()
.setMediaUri(Uri.parse(getStreamUrl()))
.setArtworkUri(Uri.parse(getThumbnailUrl())) .setArtworkUri(Uri.parse(getThumbnailUrl()))
.setArtist(getUploaderName()) .setArtist(getUploaderName())
.setDescription(getTitle()) .setDescription(getTitle())
@ -84,10 +84,15 @@ public interface MediaItemTag {
.setTitle(getTitle()) .setTitle(getTitle())
.build(); .build();
final RequestMetadata requestMetaData = new RequestMetadata.Builder()
.setMediaUri(Uri.parse(getStreamUrl()))
.build();
return MediaItem.fromUri(getStreamUrl()) return MediaItem.fromUri(getStreamUrl())
.buildUpon() .buildUpon()
.setMediaId(makeMediaId()) .setMediaId(makeMediaId())
.setMediaMetadata(mediaMetadata) .setMediaMetadata(mediaMetadata)
.setRequestMetadata(requestMetaData)
.setTag(this) .setTag(this)
.build(); .build();
} }

View file

@ -4,7 +4,7 @@ import android.content.Context;
import android.view.SurfaceHolder; import android.view.SurfaceHolder;
import com.google.android.exoplayer2.Player; 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' * Prevent error message: 'Unrecoverable player error occurred'
@ -26,7 +26,7 @@ public final class SurfaceHolderCallback implements SurfaceHolder.Callback {
private final Context context; private final Context context;
private final Player player; private final Player player;
private DummySurface dummySurface; private PlaceholderSurface placeholderSurface;
public SurfaceHolderCallback(final Context context, final Player player) { public SurfaceHolderCallback(final Context context, final Player player) {
this.context = context; this.context = context;
@ -47,16 +47,16 @@ public final class SurfaceHolderCallback implements SurfaceHolder.Callback {
@Override @Override
public void surfaceDestroyed(final SurfaceHolder holder) { public void surfaceDestroyed(final SurfaceHolder holder) {
if (dummySurface == null) { if (placeholderSurface == null) {
dummySurface = DummySurface.newInstanceV17(context, false); placeholderSurface = PlaceholderSurface.newInstanceV17(context, false);
} }
player.setVideoSurface(dummySurface); player.setVideoSurface(placeholderSurface);
} }
public void release() { public void release() {
if (dummySurface != null) { if (placeholderSurface != null) {
dummySurface.release(); placeholderSurface.release();
dummySurface = null; placeholderSurface = null;
} }
} }
} }

View file

@ -172,9 +172,10 @@ public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
try { try {
final StreamInfoTag tag = StreamInfoTag.of(info); final StreamInfoTag tag = StreamInfoTag.of(info);
if (!info.getHlsUrl().isEmpty()) { 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()) { } 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) { } catch (final Exception e) {
Log.w(TAG, "Error when generating live media source, falling back to standard sources", Log.w(TAG, "Error when generating live media source, falling back to standard sources",
@ -190,17 +191,17 @@ public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
final MediaItemTag metadata) throws ResolverException { final MediaItemTag metadata) throws ResolverException {
final MediaSource.Factory factory; final MediaSource.Factory factory;
switch (type) { switch (type) {
case C.TYPE_SS: case C.CONTENT_TYPE_SS:
factory = dataSource.getLiveSsMediaSourceFactory(); factory = dataSource.getLiveSsMediaSourceFactory();
break; break;
case C.TYPE_DASH: case C.CONTENT_TYPE_DASH:
factory = dataSource.getLiveDashMediaSourceFactory(); factory = dataSource.getLiveDashMediaSourceFactory();
break; break;
case C.TYPE_HLS: case C.CONTENT_TYPE_HLS:
factory = dataSource.getLiveHlsMediaSourceFactory(); factory = dataSource.getLiveHlsMediaSourceFactory();
break; break;
case C.TYPE_OTHER: case C.CONTENT_TYPE_OTHER:
case C.TYPE_RTSP: case C.CONTENT_TYPE_RTSP:
default: default:
throw new ResolverException("Unsupported type: " + type); throw new ResolverException("Unsupported type: " + type);
} }