diff --git a/app/build.gradle b/app/build.gradle index 114828bf3..f89f1d004 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -44,10 +44,10 @@ android { ext { supportLibVersion = '28.0.0' - exoPlayerLibVersion = '2.8.4' //2.9.0 + exoPlayerLibVersion = '2.9.6' roomDbLibVersion = '1.1.1' leakCanaryLibVersion = '1.5.4' //1.6.1 - okHttpLibVersion = '3.11.0' + okHttpLibVersion = '3.12.1' icepickLibVersion = '3.2.0' stethoLibVersion = '1.5.0' } diff --git a/app/src/main/java/org/schabi/newpipe/download/DownloadActivity.java b/app/src/main/java/org/schabi/newpipe/download/DownloadActivity.java index 251e4c730..7ee686a66 100644 --- a/app/src/main/java/org/schabi/newpipe/download/DownloadActivity.java +++ b/app/src/main/java/org/schabi/newpipe/download/DownloadActivity.java @@ -47,7 +47,7 @@ public class DownloadActivity extends AppCompatActivity { @Override public void onGlobalLayout() { updateFragments(); - getWindow().getDecorView().getViewTreeObserver().removeGlobalOnLayoutListener(this); + getWindow().getDecorView().getViewTreeObserver().removeOnGlobalLayoutListener(this); } }); } 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 d1b06c9c5..4d5f29148 100644 --- a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java @@ -44,6 +44,7 @@ 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; @@ -63,7 +64,6 @@ 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 CustomTrackSelector trackSelector; + final protected DefaultTrackSelector trackSelector; @NonNull final protected PlayerDataSource dataSource; @@ -207,9 +207,8 @@ public abstract class BasePlayer implements final DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(); this.dataSource = new PlayerDataSource(context, userAgent, bandwidthMeter); - final TrackSelection.Factory trackSelectionFactory = - PlayerHelper.getQualitySelector(context, bandwidthMeter); - this.trackSelector = new CustomTrackSelector(trackSelectionFactory); + final TrackSelection.Factory trackSelectionFactory = PlayerHelper.getQualitySelector(context); + this.trackSelector = new DefaultTrackSelector(trackSelectionFactory); this.loadControl = new LoadController(context); this.renderFactory = new DefaultRenderersFactory(context); @@ -225,7 +224,7 @@ public abstract class BasePlayer implements public void initPlayer(final boolean playOnReady) { if (DEBUG) Log.d(TAG, "initPlayer() called with: context = [" + context + "]"); - simpleExoPlayer = ExoPlayerFactory.newSimpleInstance(renderFactory, trackSelector, loadControl); + simpleExoPlayer = ExoPlayerFactory.newSimpleInstance(context, renderFactory, trackSelector, loadControl); simpleExoPlayer.addListener(this); simpleExoPlayer.setPlayWhenReady(playOnReady); simpleExoPlayer.setSeekParameters(PlayerHelper.getSeekParameters(context)); diff --git a/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java b/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java index 5dd931b54..778a91c79 100644 --- a/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java @@ -282,14 +282,9 @@ public final class MainVideoPlayer extends AppCompatActivity if (DEBUG) Log.d(TAG, "showSystemUi() called"); if (playerImpl != null && playerImpl.queueVisible) return; - final int visibility; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - visibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE + final int visibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; - } else { - visibility = View.STATUS_BAR_VISIBLE; - } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { @ColorInt final int systenUiColor = @@ -358,11 +353,7 @@ public final class MainVideoPlayer extends AppCompatActivity protected void setShuffleButton(final ImageButton shuffleButton, final boolean shuffled) { final int shuffleAlpha = shuffled ? 255 : 77; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - shuffleButton.setImageAlpha(shuffleAlpha); - } else { - shuffleButton.setAlpha(shuffleAlpha); - } + shuffleButton.setImageAlpha(shuffleAlpha); } private boolean isInMultiWindow() { diff --git a/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java b/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java index 2ec4275fc..3e04f1e3a 100644 --- a/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java +++ b/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java @@ -3,7 +3,6 @@ package org.schabi.newpipe.player; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; -import android.os.Build; import android.os.Bundle; import android.os.IBinder; import android.provider.Settings; @@ -653,11 +652,7 @@ public abstract class ServicePlayerActivity extends AppCompatActivity } final int shuffleAlpha = shuffled ? 255 : 77; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - shuffleButton.setImageAlpha(shuffleAlpha); - } else { - shuffleButton.setAlpha(shuffleAlpha); - } + shuffleButton.setImageAlpha(shuffleAlpha); } private void onPlaybackParameterChanged(final PlaybackParameters parameters) { 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 d30d9b8be..fb60ac473 100644 --- a/app/src/main/java/org/schabi/newpipe/player/VideoPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/VideoPlayer.java @@ -212,7 +212,6 @@ public abstract class VideoPlayer extends BasePlayer @Override public void initListeners() { - super.initListeners(); playbackSeekBar.setOnSeekBarChangeListener(this); playbackSpeedTextView.setOnClickListener(this); qualityTextView.setOnClickListener(this); @@ -306,9 +305,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)); + .setRendererDisabled(textRendererIndex, false) + .setPreferredTextLanguage(captionLanguage)); } return true; }); @@ -509,12 +508,12 @@ public abstract class VideoPlayer extends BasePlayer } // Normalize mismatching language strings - final String preferredLanguage = trackSelector.getPreferredTextLanguage(); - + final String preferredLanguage = trackSelector.getParameters().preferredTextLanguage; // Build UI buildCaptionMenu(availableLanguages); if (trackSelector.getParameters().getRendererDisabled(textRenderer) || - preferredLanguage == null || !availableLanguages.contains(preferredLanguage)) { + preferredLanguage == null || (!availableLanguages.contains(preferredLanguage) + && !containsCaseInsensitive(availableLanguages, preferredLanguage))) { captionTextView.setText(R.string.caption_none); } else { captionTextView.setText(preferredLanguage); @@ -522,6 +521,15 @@ public abstract class VideoPlayer extends BasePlayer captionTextView.setVisibility(availableLanguages.isEmpty() ? View.GONE : View.VISIBLE); } + // workaround to match normalized captions like english to English or deutsch to Deutsch + private static boolean containsCaseInsensitive(List list, String toFind) { + for(String i : list){ + if(i.equalsIgnoreCase(toFind)) + return true; + } + return false; + } + /*////////////////////////////////////////////////////////////////////////// // General Player //////////////////////////////////////////////////////////////////////////*/ diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/AudioReactor.java b/app/src/main/java/org/schabi/newpipe/player/helper/AudioReactor.java index f148aed27..24d1ee1ca 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/AudioReactor.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/AudioReactor.java @@ -12,13 +12,11 @@ import android.os.Build; import android.support.annotation.NonNull; import android.util.Log; -import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.SimpleExoPlayer; -import com.google.android.exoplayer2.audio.AudioRendererEventListener; -import com.google.android.exoplayer2.decoder.DecoderCounters; +import com.google.android.exoplayer2.analytics.AnalyticsListener; public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, - AudioRendererEventListener { + AnalyticsListener { private static final String TAG = "AudioFocusReactor"; @@ -42,7 +40,7 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, this.player = player; this.context = context; this.audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); - player.addAudioDebugListener(this); + player.addAnalyticsListener(this); if (SHOULD_BUILD_FOCUS_REQUEST) { request = new AudioFocusRequest.Builder(FOCUS_GAIN_TYPE) @@ -57,7 +55,7 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, public void dispose() { abandonAudioFocus(); - player.removeAudioDebugListener(this); + player.removeAnalyticsListener(this); } /*////////////////////////////////////////////////////////////////////////// @@ -164,29 +162,12 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, //////////////////////////////////////////////////////////////////////////*/ @Override - public void onAudioSessionId(int i) { + public void onAudioSessionId(EventTime eventTime, int audioSessionId) { if (!PlayerHelper.isUsingDSP(context)) return; final Intent intent = new Intent(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION); - intent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, i); + intent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, audioSessionId); intent.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, context.getPackageName()); context.sendBroadcast(intent); } - - @Override - public void onAudioEnabled(DecoderCounters decoderCounters) {} - - @Override - public void onAudioDecoderInitialized(String s, long l, long l1) {} - - @Override - public void onAudioInputFormatChanged(Format format) {} - - @Override - public void onAudioSinkUnderrun(int bufferSize, - long bufferSizeMs, - long elapsedSinceLastFeedMs) {} - - @Override - public void onAudioDisabled(DecoderCounters decoderCounters) {} } diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/CacheFactory.java b/app/src/main/java/org/schabi/newpipe/player/helper/CacheFactory.java index b8d8dc12f..091efc942 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/CacheFactory.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/CacheFactory.java @@ -33,14 +33,14 @@ import java.io.File; public CacheFactory(@NonNull final Context context, @NonNull final String userAgent, - @NonNull final TransferListener transferListener) { + @NonNull final TransferListener transferListener) { this(context, userAgent, transferListener, PlayerHelper.getPreferredCacheSize(context), PlayerHelper.getPreferredFileSize(context)); } private CacheFactory(@NonNull final Context context, @NonNull final String userAgent, - @NonNull final TransferListener transferListener, + @NonNull final TransferListener transferListener, final long maxCacheSize, final long maxFileSize) { this.maxFileSize = maxFileSize; diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/LoadController.java b/app/src/main/java/org/schabi/newpipe/player/helper/LoadController.java index 7670deb98..4239dd62f 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/LoadController.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/LoadController.java @@ -2,17 +2,12 @@ package org.schabi.newpipe.player.helper; import android.content.Context; -import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.DefaultLoadControl; import com.google.android.exoplayer2.LoadControl; import com.google.android.exoplayer2.Renderer; import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.trackselection.TrackSelectionArray; import com.google.android.exoplayer2.upstream.Allocator; -import com.google.android.exoplayer2.upstream.DefaultAllocator; - -import static com.google.android.exoplayer2.DefaultLoadControl.DEFAULT_PRIORITIZE_TIME_OVER_SIZE_THRESHOLDS; -import static com.google.android.exoplayer2.DefaultLoadControl.DEFAULT_TARGET_BUFFER_BYTES; public class LoadController implements LoadControl { @@ -36,15 +31,10 @@ public class LoadController implements LoadControl { final int optimalPlaybackBufferMs) { this.initialPlaybackBufferUs = initialPlaybackBufferMs * 1000; - final DefaultAllocator allocator = new DefaultAllocator(true, - C.DEFAULT_BUFFER_SEGMENT_SIZE); - - internalLoadControl = new DefaultLoadControl(allocator, - /*minBufferMs=*/minimumPlaybackbufferMs, - /*maxBufferMs=*/optimalPlaybackBufferMs, - /*bufferForPlaybackMs=*/initialPlaybackBufferMs, - /*bufferForPlaybackAfterRebufferMs=*/initialPlaybackBufferMs, - DEFAULT_TARGET_BUFFER_BYTES, DEFAULT_PRIORITIZE_TIME_OVER_SIZE_THRESHOLDS); + DefaultLoadControl.Builder builder = new DefaultLoadControl.Builder(); + builder.setBufferDurationsMs(minimumPlaybackbufferMs, optimalPlaybackBufferMs, + initialPlaybackBufferMs, initialPlaybackBufferMs); + internalLoadControl = builder.createDefaultLoadControl(); } /*////////////////////////////////////////////////////////////////////////// diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java index 133121269..5743891c2 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java @@ -12,6 +12,7 @@ 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.DefaultLoadErrorHandlingPolicy; import com.google.android.exoplayer2.upstream.TransferListener; public class PlayerDataSource { @@ -24,7 +25,7 @@ public class PlayerDataSource { public PlayerDataSource(@NonNull final Context context, @NonNull final String userAgent, - @NonNull final TransferListener transferListener) { + @NonNull final TransferListener transferListener) { cacheDataSourceFactory = new CacheFactory(context, userAgent, transferListener); cachelessDataSourceFactory = new DefaultDataSourceFactory(context, userAgent, transferListener); } @@ -32,21 +33,21 @@ public class PlayerDataSource { public SsMediaSource.Factory getLiveSsMediaSourceFactory() { return new SsMediaSource.Factory(new DefaultSsChunkSource.Factory( cachelessDataSourceFactory), cachelessDataSourceFactory) - .setMinLoadableRetryCount(MANIFEST_MINIMUM_RETRY) + .setLoadErrorHandlingPolicy(new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY)) .setLivePresentationDelayMs(LIVE_STREAM_EDGE_GAP_MILLIS); } public HlsMediaSource.Factory getLiveHlsMediaSourceFactory() { return new HlsMediaSource.Factory(cachelessDataSourceFactory) .setAllowChunklessPreparation(true) - .setMinLoadableRetryCount(MANIFEST_MINIMUM_RETRY); + .setLoadErrorHandlingPolicy(new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY)); } public DashMediaSource.Factory getLiveDashMediaSourceFactory() { return new DashMediaSource.Factory(new DefaultDashChunkSource.Factory( cachelessDataSourceFactory), cachelessDataSourceFactory) - .setMinLoadableRetryCount(MANIFEST_MINIMUM_RETRY) - .setLivePresentationDelayMs(LIVE_STREAM_EDGE_GAP_MILLIS); + .setLoadErrorHandlingPolicy(new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY)) + .setLivePresentationDelayMs(LIVE_STREAM_EDGE_GAP_MILLIS, true); } public SsMediaSource.Factory getSsMediaSourceFactory() { @@ -65,7 +66,7 @@ public class PlayerDataSource { public ExtractorMediaSource.Factory getExtractorMediaSourceFactory() { return new ExtractorMediaSource.Factory(cacheDataSourceFactory) - .setMinLoadableRetryCount(EXTRACTOR_MINIMUM_RETRY); + .setLoadErrorHandlingPolicy(new DefaultLoadErrorHandlingPolicy(EXTRACTOR_MINIMUM_RETRY)); } public ExtractorMediaSource.Factory getExtractorMediaSourceFactory(@NonNull final String key) { diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java index 7752295d7..7248857b5 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java @@ -14,7 +14,6 @@ import com.google.android.exoplayer2.text.CaptionStyleCompat; import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; -import com.google.android.exoplayer2.upstream.BandwidthMeter; import com.google.android.exoplayer2.util.MimeTypes; import org.schabi.newpipe.R; @@ -240,9 +239,8 @@ public class PlayerHelper { return 60000; } - public static TrackSelection.Factory getQualitySelector(@NonNull final Context context, - @NonNull final BandwidthMeter meter) { - return new AdaptiveTrackSelection.Factory(meter, + public static TrackSelection.Factory getQualitySelector(@NonNull final Context context) { + return new AdaptiveTrackSelection.Factory( /*bufferDurationRequiredForQualityIncrease=*/1000, AdaptiveTrackSelection.DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS, AdaptiveTrackSelection.DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS, diff --git a/app/src/main/java/org/schabi/newpipe/player/mediasource/FailedMediaSource.java b/app/src/main/java/org/schabi/newpipe/player/mediasource/FailedMediaSource.java index 2f233c464..cc9cd36bc 100644 --- a/app/src/main/java/org/schabi/newpipe/player/mediasource/FailedMediaSource.java +++ b/app/src/main/java/org/schabi/newpipe/player/mediasource/FailedMediaSource.java @@ -1,12 +1,13 @@ package org.schabi.newpipe.player.mediasource; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.util.Log; -import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.source.BaseMediaSource; import com.google.android.exoplayer2.source.MediaPeriod; import com.google.android.exoplayer2.upstream.Allocator; +import com.google.android.exoplayer2.upstream.TransferListener; import org.schabi.newpipe.player.playqueue.PlayQueueItem; @@ -79,7 +80,7 @@ public class FailedMediaSource extends BaseMediaSource implements ManagedMediaSo } @Override - public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) { + public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) { return null; } @@ -88,7 +89,7 @@ public class FailedMediaSource extends BaseMediaSource implements ManagedMediaSo @Override - protected void prepareSourceInternal(ExoPlayer player, boolean isTopLevelSource) { + protected void prepareSourceInternal(@Nullable TransferListener mediaTransferListener) { Log.e(TAG, "Loading failed source: ", error); } diff --git a/app/src/main/java/org/schabi/newpipe/player/mediasource/LoadedMediaSource.java b/app/src/main/java/org/schabi/newpipe/player/mediasource/LoadedMediaSource.java index c39b0a03d..d36a3e305 100644 --- a/app/src/main/java/org/schabi/newpipe/player/mediasource/LoadedMediaSource.java +++ b/app/src/main/java/org/schabi/newpipe/player/mediasource/LoadedMediaSource.java @@ -2,12 +2,13 @@ package org.schabi.newpipe.player.mediasource; import android.os.Handler; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; -import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.source.MediaPeriod; import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.MediaSourceEventListener; import com.google.android.exoplayer2.upstream.Allocator; +import com.google.android.exoplayer2.upstream.TransferListener; import org.schabi.newpipe.player.playqueue.PlayQueueItem; @@ -36,9 +37,8 @@ public class LoadedMediaSource implements ManagedMediaSource { } @Override - public void prepareSource(ExoPlayer player, boolean isTopLevelSource, - SourceInfoRefreshListener listener) { - source.prepareSource(player, isTopLevelSource, listener); + public void prepareSource(SourceInfoRefreshListener listener, @Nullable TransferListener mediaTransferListener) { + source.prepareSource(listener, mediaTransferListener); } @Override @@ -47,8 +47,8 @@ public class LoadedMediaSource implements ManagedMediaSource { } @Override - public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) { - return source.createPeriod(id, allocator); + public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) { + return source.createPeriod(id, allocator, startPositionUs); } @Override diff --git a/app/src/main/java/org/schabi/newpipe/player/mediasource/ManagedMediaSourcePlaylist.java b/app/src/main/java/org/schabi/newpipe/player/mediasource/ManagedMediaSourcePlaylist.java index 5fe107657..fe29707fc 100644 --- a/app/src/main/java/org/schabi/newpipe/player/mediasource/ManagedMediaSourcePlaylist.java +++ b/app/src/main/java/org/schabi/newpipe/player/mediasource/ManagedMediaSourcePlaylist.java @@ -1,5 +1,5 @@ package org.schabi.newpipe.player.mediasource; - +import android.os.Handler; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -86,21 +86,22 @@ public class ManagedMediaSourcePlaylist { /** * Invalidates the {@link ManagedMediaSource} at the given index by replacing it * with a {@link PlaceholderMediaSource}. - * @see #update(int, ManagedMediaSource, Runnable) + * @see #update(int, ManagedMediaSource, Handler, Runnable) * */ public synchronized void invalidate(final int index, + @Nullable final Handler handler, @Nullable final Runnable finalizingAction) { if (get(index) instanceof PlaceholderMediaSource) return; - update(index, new PlaceholderMediaSource(), finalizingAction); + update(index, new PlaceholderMediaSource(), handler, finalizingAction); } /** * Updates the {@link ManagedMediaSource} in {@link ConcatenatingMediaSource} * at the given index with a given {@link ManagedMediaSource}. - * @see #update(int, ManagedMediaSource, Runnable) + * @see #update(int, ManagedMediaSource, Handler, Runnable) * */ public synchronized void update(final int index, @NonNull final ManagedMediaSource source) { - update(index, source, /*doNothing=*/null); + update(index, source, null, /*doNothing=*/null); } /** @@ -108,9 +109,10 @@ public class ManagedMediaSourcePlaylist { * at the given index with a given {@link ManagedMediaSource}. If the index is out of bound, * then the replacement is ignored. * @see ConcatenatingMediaSource#addMediaSource - * @see ConcatenatingMediaSource#removeMediaSource(int, Runnable) + * @see ConcatenatingMediaSource#removeMediaSource(int, Handler, Runnable) * */ public synchronized void update(final int index, @NonNull final ManagedMediaSource source, + @Nullable final Handler handler, @Nullable final Runnable finalizingAction) { if (index < 0 || index >= internalSource.getSize()) return; @@ -126,6 +128,6 @@ public class ManagedMediaSourcePlaylist { // Because of the above race condition, it is thus only safe to synchronize the player // in the finalizing action AFTER the removal is complete and the timeline has changed. - internalSource.removeMediaSource(index, finalizingAction); + internalSource.removeMediaSource(index, handler, finalizingAction); } } diff --git a/app/src/main/java/org/schabi/newpipe/player/mediasource/PlaceholderMediaSource.java b/app/src/main/java/org/schabi/newpipe/player/mediasource/PlaceholderMediaSource.java index bfd734393..377ca55a3 100644 --- a/app/src/main/java/org/schabi/newpipe/player/mediasource/PlaceholderMediaSource.java +++ b/app/src/main/java/org/schabi/newpipe/player/mediasource/PlaceholderMediaSource.java @@ -1,20 +1,21 @@ package org.schabi.newpipe.player.mediasource; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; -import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.source.BaseMediaSource; import com.google.android.exoplayer2.source.MediaPeriod; import com.google.android.exoplayer2.upstream.Allocator; +import com.google.android.exoplayer2.upstream.TransferListener; import org.schabi.newpipe.player.playqueue.PlayQueueItem; public class PlaceholderMediaSource extends BaseMediaSource implements ManagedMediaSource { // Do nothing, so this will stall the playback @Override public void maybeThrowSourceInfoRefreshError() {} - @Override public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) { return null; } + @Override public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) { return null; } @Override public void releasePeriod(MediaPeriod mediaPeriod) {} - @Override protected void prepareSourceInternal(ExoPlayer player, boolean isTopLevelSource) {} + @Override protected void prepareSourceInternal(@Nullable TransferListener mediaTransferListener) {} @Override protected void releaseSourceInternal() {} @Override 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 deleted file mode 100644 index efe6f3a58..000000000 --- a/app/src/main/java/org/schabi/newpipe/player/playback/CustomTrackSelector.java +++ /dev/null @@ -1,112 +0,0 @@ -package org.schabi.newpipe.player.playback; - -import android.support.annotation.NonNull; -import android.text.TextUtils; - -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 TrackSelection 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 - : new FixedTrackSelection(selectedGroup, selectedTrackIndex); - } -} diff --git a/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java b/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java index 3c5642d51..db8cc797e 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java +++ b/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java @@ -1,5 +1,5 @@ package org.schabi.newpipe.player.playback; - +import android.os.Handler; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.util.ArraySet; @@ -103,6 +103,8 @@ public class MediaSourceManager { @NonNull private ManagedMediaSourcePlaylist playlist; + private Handler removeMediaSourceHandler = new Handler(); + public MediaSourceManager(@NonNull final PlaybackListener listener, @NonNull final PlayQueue playQueue) { this(listener, playQueue, /*loadDebounceMillis=*/400L, @@ -395,7 +397,7 @@ public class MediaSourceManager { if (isCorrectionNeeded(item)) { if (DEBUG) Log.d(TAG, "MediaSource - Updating index=[" + itemIndex + "] with " + "title=[" + item.getTitle() + "] at url=[" + item.getUrl() + "]"); - playlist.update(itemIndex, mediaSource, this::maybeSynchronizePlayer); + playlist.update(itemIndex, mediaSource, removeMediaSourceHandler, this::maybeSynchronizePlayer); } } @@ -441,7 +443,7 @@ public class MediaSourceManager { if (DEBUG) Log.d(TAG, "MediaSource - Reloading currently playing, " + "index=[" + currentIndex + "], item=[" + currentItem.getTitle() + "]"); - playlist.invalidate(currentIndex, this::loadImmediate); + playlist.invalidate(currentIndex, removeMediaSourceHandler, this::loadImmediate); } private void maybeClearLoaders() {