From 0763280196ab54873a441254ab8642be018da232 Mon Sep 17 00:00:00 2001 From: Robin Date: Sun, 28 Apr 2019 01:45:19 +0200 Subject: [PATCH] Readd CustomTrackSelector --- .../org/schabi/newpipe/player/BasePlayer.java | 6 +- .../schabi/newpipe/player/VideoPlayer.java | 6 +- .../player/playback/CustomTrackSelector.java | 115 ++++++++++++++++++ 3 files changed, 120 insertions(+), 7 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/player/playback/CustomTrackSelector.java diff --git a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java index 22c69fdd4..3db4be4a6 100644 --- a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java @@ -44,7 +44,6 @@ import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.source.BehindLiveWindowException; import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.TrackGroupArray; -import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelectionArray; import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; @@ -64,6 +63,7 @@ import org.schabi.newpipe.player.helper.PlayerDataSource; import org.schabi.newpipe.player.helper.PlayerHelper; import org.schabi.newpipe.player.mediasource.FailedMediaSource; import org.schabi.newpipe.player.playback.BasePlayerMediaSession; +import org.schabi.newpipe.player.playback.CustomTrackSelector; import org.schabi.newpipe.player.playback.MediaSourceManager; import org.schabi.newpipe.player.playback.PlaybackListener; import org.schabi.newpipe.player.playqueue.PlayQueue; @@ -113,7 +113,7 @@ public abstract class BasePlayer implements final protected HistoryRecordManager recordManager; @NonNull - final protected DefaultTrackSelector trackSelector; + final protected CustomTrackSelector trackSelector; @NonNull final protected PlayerDataSource dataSource; @@ -208,7 +208,7 @@ public abstract class BasePlayer implements this.dataSource = new PlayerDataSource(context, userAgent, bandwidthMeter); final TrackSelection.Factory trackSelectionFactory = PlayerHelper.getQualitySelector(context); - this.trackSelector = new DefaultTrackSelector(trackSelectionFactory); + this.trackSelector = new CustomTrackSelector(trackSelectionFactory); this.loadControl = new LoadController(context); this.renderFactory = new DefaultRenderersFactory(context); diff --git a/app/src/main/java/org/schabi/newpipe/player/VideoPlayer.java b/app/src/main/java/org/schabi/newpipe/player/VideoPlayer.java index fb60ac473..4dbbc571d 100644 --- a/app/src/main/java/org/schabi/newpipe/player/VideoPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/VideoPlayer.java @@ -297,7 +297,6 @@ public abstract class VideoPlayer extends BasePlayer return true; }); - // Add all available captions for (int i = 0; i < availableLanguages.size(); i++) { final String captionLanguage = availableLanguages.get(i); MenuItem captionItem = captionPopupMenu.getMenu().add(captionPopupMenuGroupId, @@ -305,9 +304,9 @@ public abstract class VideoPlayer extends BasePlayer captionItem.setOnMenuItemClickListener(menuItem -> { final int textRendererIndex = getRendererIndex(C.TRACK_TYPE_TEXT); if (textRendererIndex != RENDERER_UNAVAILABLE) { + trackSelector.setPreferredTextLanguage(captionLanguage); trackSelector.setParameters(trackSelector.buildUponParameters() - .setRendererDisabled(textRendererIndex, false) - .setPreferredTextLanguage(captionLanguage)); + .setRendererDisabled(textRendererIndex, false)); } return true; }); @@ -315,7 +314,6 @@ public abstract class VideoPlayer extends BasePlayer captionPopupMenu.setOnDismissListener(this); } - private void updateStreamRelatedViews() { if (getCurrentMetadata() == null) return; diff --git a/app/src/main/java/org/schabi/newpipe/player/playback/CustomTrackSelector.java b/app/src/main/java/org/schabi/newpipe/player/playback/CustomTrackSelector.java new file mode 100644 index 000000000..063d6b93e --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/player/playback/CustomTrackSelector.java @@ -0,0 +1,115 @@ +package org.schabi.newpipe.player.playback; + +import android.support.annotation.NonNull; +import android.text.TextUtils; +import android.util.Pair; + +import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.Format; +import com.google.android.exoplayer2.source.TrackGroup; +import com.google.android.exoplayer2.source.TrackGroupArray; +import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; +import com.google.android.exoplayer2.trackselection.FixedTrackSelection; +import com.google.android.exoplayer2.trackselection.TrackSelection; +import com.google.android.exoplayer2.util.Assertions; + +/** + * This class allows irregular text language labels for use when selecting text captions and + * is mostly a copy-paste from {@link DefaultTrackSelector}. + * + * This is a hack and should be removed once ExoPlayer fixes language normalization to accept + * a broader set of languages. + * */ +public class CustomTrackSelector extends DefaultTrackSelector { + private static final int WITHIN_RENDERER_CAPABILITIES_BONUS = 1000; + + private String preferredTextLanguage; + + public CustomTrackSelector(TrackSelection.Factory adaptiveTrackSelectionFactory) { + super(adaptiveTrackSelectionFactory); + } + + public String getPreferredTextLanguage() { + return preferredTextLanguage; + } + + public void setPreferredTextLanguage(@NonNull final String label) { + Assertions.checkNotNull(label); + if (!label.equals(preferredTextLanguage)) { + preferredTextLanguage = label; + invalidate(); + } + } + + /** @see DefaultTrackSelector#formatHasLanguage(Format, String)*/ + protected static boolean formatHasLanguage(Format format, String language) { + return language != null && TextUtils.equals(language, format.language); + } + + /** @see DefaultTrackSelector#formatHasNoLanguage(Format)*/ + protected static boolean formatHasNoLanguage(Format format) { + return TextUtils.isEmpty(format.language) || formatHasLanguage(format, C.LANGUAGE_UNDETERMINED); + } + + /** @see DefaultTrackSelector#selectTextTrack(TrackGroupArray, int[][], Parameters) */ + @Override + protected Pair selectTextTrack(TrackGroupArray groups, int[][] formatSupport, + Parameters params) { + TrackGroup selectedGroup = null; + int selectedTrackIndex = 0; + int selectedTrackScore = 0; + for (int groupIndex = 0; groupIndex < groups.length; groupIndex++) { + TrackGroup trackGroup = groups.get(groupIndex); + int[] trackFormatSupport = formatSupport[groupIndex]; + for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) { + if (isSupported(trackFormatSupport[trackIndex], + params.exceedRendererCapabilitiesIfNecessary)) { + Format format = trackGroup.getFormat(trackIndex); + int maskedSelectionFlags = + format.selectionFlags & ~params.disabledTextTrackSelectionFlags; + boolean isDefault = (maskedSelectionFlags & C.SELECTION_FLAG_DEFAULT) != 0; + boolean isForced = (maskedSelectionFlags & C.SELECTION_FLAG_FORCED) != 0; + int trackScore; + boolean preferredLanguageFound = formatHasLanguage(format, preferredTextLanguage); + if (preferredLanguageFound + || (params.selectUndeterminedTextLanguage && formatHasNoLanguage(format))) { + if (isDefault) { + trackScore = 8; + } else if (!isForced) { + // Prefer non-forced to forced if a preferred text language has been specified. Where + // both are provided the non-forced track will usually contain the forced subtitles as + // a subset. + trackScore = 6; + } else { + trackScore = 4; + } + trackScore += preferredLanguageFound ? 1 : 0; + } else if (isDefault) { + trackScore = 3; + } else if (isForced) { + if (formatHasLanguage(format, params.preferredAudioLanguage)) { + trackScore = 2; + } else { + trackScore = 1; + } + } else { + // Track should not be selected. + continue; + } + if (isSupported(trackFormatSupport[trackIndex], false)) { + trackScore += WITHIN_RENDERER_CAPABILITIES_BONUS; + } + if (trackScore > selectedTrackScore) { + selectedGroup = trackGroup; + selectedTrackIndex = trackIndex; + selectedTrackScore = trackScore; + } + } + } + } + return selectedGroup == null + ? null + : Pair.create( + new FixedTrackSelection(selectedGroup, selectedTrackIndex), selectedTrackScore); + } +} \ No newline at end of file