mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-30 23:03:00 +00:00 
			
		
		
		
	Merge remote-tracking branch 'upstream/dev' into defaultTrending
This commit is contained in:
		| @@ -44,10 +44,10 @@ android { | |||||||
|  |  | ||||||
| ext { | ext { | ||||||
|     supportLibVersion = '28.0.0' |     supportLibVersion = '28.0.0' | ||||||
|     exoPlayerLibVersion = '2.8.4' //2.9.0 |     exoPlayerLibVersion = '2.9.6' | ||||||
|     roomDbLibVersion = '1.1.1' |     roomDbLibVersion = '1.1.1' | ||||||
|     leakCanaryLibVersion = '1.5.4' //1.6.1 |     leakCanaryLibVersion = '1.5.4' //1.6.1 | ||||||
|     okHttpLibVersion = '3.11.0' |     okHttpLibVersion = '3.12.1' | ||||||
|     icepickLibVersion = '3.2.0' |     icepickLibVersion = '3.2.0' | ||||||
|     stethoLibVersion = '1.5.0' |     stethoLibVersion = '1.5.0' | ||||||
| } | } | ||||||
|   | |||||||
| @@ -47,7 +47,7 @@ public class DownloadActivity extends AppCompatActivity { | |||||||
|             @Override |             @Override | ||||||
|             public void onGlobalLayout() { |             public void onGlobalLayout() { | ||||||
|                 updateFragments(); |                 updateFragments(); | ||||||
|                 getWindow().getDecorView().getViewTreeObserver().removeGlobalOnLayoutListener(this); |                 getWindow().getDecorView().getViewTreeObserver().removeOnGlobalLayoutListener(this); | ||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -44,6 +44,7 @@ import com.google.android.exoplayer2.Timeline; | |||||||
| import com.google.android.exoplayer2.source.BehindLiveWindowException; | import com.google.android.exoplayer2.source.BehindLiveWindowException; | ||||||
| import com.google.android.exoplayer2.source.MediaSource; | import com.google.android.exoplayer2.source.MediaSource; | ||||||
| import com.google.android.exoplayer2.source.TrackGroupArray; | 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.TrackSelection; | ||||||
| import com.google.android.exoplayer2.trackselection.TrackSelectionArray; | import com.google.android.exoplayer2.trackselection.TrackSelectionArray; | ||||||
| import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; | 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.helper.PlayerHelper; | ||||||
| import org.schabi.newpipe.player.mediasource.FailedMediaSource; | import org.schabi.newpipe.player.mediasource.FailedMediaSource; | ||||||
| import org.schabi.newpipe.player.playback.BasePlayerMediaSession; | 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.MediaSourceManager; | ||||||
| import org.schabi.newpipe.player.playback.PlaybackListener; | import org.schabi.newpipe.player.playback.PlaybackListener; | ||||||
| import org.schabi.newpipe.player.playqueue.PlayQueue; | import org.schabi.newpipe.player.playqueue.PlayQueue; | ||||||
| @@ -113,7 +113,7 @@ public abstract class BasePlayer implements | |||||||
|     final protected HistoryRecordManager recordManager; |     final protected HistoryRecordManager recordManager; | ||||||
|  |  | ||||||
|     @NonNull |     @NonNull | ||||||
|     final protected CustomTrackSelector trackSelector; |     final protected DefaultTrackSelector trackSelector; | ||||||
|     @NonNull |     @NonNull | ||||||
|     final protected PlayerDataSource dataSource; |     final protected PlayerDataSource dataSource; | ||||||
|  |  | ||||||
| @@ -207,9 +207,8 @@ public abstract class BasePlayer implements | |||||||
|         final DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(); |         final DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(); | ||||||
|         this.dataSource = new PlayerDataSource(context, userAgent, bandwidthMeter); |         this.dataSource = new PlayerDataSource(context, userAgent, bandwidthMeter); | ||||||
|  |  | ||||||
|         final TrackSelection.Factory trackSelectionFactory = |         final TrackSelection.Factory trackSelectionFactory = PlayerHelper.getQualitySelector(context); | ||||||
|                 PlayerHelper.getQualitySelector(context, bandwidthMeter); |         this.trackSelector = new DefaultTrackSelector(trackSelectionFactory); | ||||||
|         this.trackSelector = new CustomTrackSelector(trackSelectionFactory); |  | ||||||
|  |  | ||||||
|         this.loadControl = new LoadController(context); |         this.loadControl = new LoadController(context); | ||||||
|         this.renderFactory = new DefaultRenderersFactory(context); |         this.renderFactory = new DefaultRenderersFactory(context); | ||||||
| @@ -225,7 +224,7 @@ public abstract class BasePlayer implements | |||||||
|     public void initPlayer(final boolean playOnReady) { |     public void initPlayer(final boolean playOnReady) { | ||||||
|         if (DEBUG) Log.d(TAG, "initPlayer() called with: context = [" + context + "]"); |         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.addListener(this); | ||||||
|         simpleExoPlayer.setPlayWhenReady(playOnReady); |         simpleExoPlayer.setPlayWhenReady(playOnReady); | ||||||
|         simpleExoPlayer.setSeekParameters(PlayerHelper.getSeekParameters(context)); |         simpleExoPlayer.setSeekParameters(PlayerHelper.getSeekParameters(context)); | ||||||
|   | |||||||
| @@ -282,14 +282,9 @@ public final class MainVideoPlayer extends AppCompatActivity | |||||||
|         if (DEBUG) Log.d(TAG, "showSystemUi() called"); |         if (DEBUG) Log.d(TAG, "showSystemUi() called"); | ||||||
|         if (playerImpl != null && playerImpl.queueVisible) return; |         if (playerImpl != null && playerImpl.queueVisible) return; | ||||||
|  |  | ||||||
|         final int visibility; |         final int visibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | ||||||
|         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { |  | ||||||
|             visibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE |  | ||||||
|                     | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |                     | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | ||||||
|                     | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; |                     | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; | ||||||
|         } else { |  | ||||||
|             visibility = View.STATUS_BAR_VISIBLE; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { |         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { | ||||||
|             @ColorInt final int systenUiColor = |             @ColorInt final int systenUiColor = | ||||||
| @@ -358,11 +353,7 @@ public final class MainVideoPlayer extends AppCompatActivity | |||||||
|  |  | ||||||
|     protected void setShuffleButton(final ImageButton shuffleButton, final boolean shuffled) { |     protected void setShuffleButton(final ImageButton shuffleButton, final boolean shuffled) { | ||||||
|         final int shuffleAlpha = shuffled ? 255 : 77; |         final int shuffleAlpha = shuffled ? 255 : 77; | ||||||
|         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { |  | ||||||
|         shuffleButton.setImageAlpha(shuffleAlpha); |         shuffleButton.setImageAlpha(shuffleAlpha); | ||||||
|         } else { |  | ||||||
|             shuffleButton.setAlpha(shuffleAlpha); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private boolean isInMultiWindow() { |     private boolean isInMultiWindow() { | ||||||
|   | |||||||
| @@ -3,7 +3,6 @@ package org.schabi.newpipe.player; | |||||||
| import android.content.ComponentName; | import android.content.ComponentName; | ||||||
| import android.content.Intent; | import android.content.Intent; | ||||||
| import android.content.ServiceConnection; | import android.content.ServiceConnection; | ||||||
| import android.os.Build; |  | ||||||
| import android.os.Bundle; | import android.os.Bundle; | ||||||
| import android.os.IBinder; | import android.os.IBinder; | ||||||
| import android.provider.Settings; | import android.provider.Settings; | ||||||
| @@ -653,11 +652,7 @@ public abstract class ServicePlayerActivity extends AppCompatActivity | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         final int shuffleAlpha = shuffled ? 255 : 77; |         final int shuffleAlpha = shuffled ? 255 : 77; | ||||||
|         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { |  | ||||||
|         shuffleButton.setImageAlpha(shuffleAlpha); |         shuffleButton.setImageAlpha(shuffleAlpha); | ||||||
|         } else { |  | ||||||
|             shuffleButton.setAlpha(shuffleAlpha); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void onPlaybackParameterChanged(final PlaybackParameters parameters) { |     private void onPlaybackParameterChanged(final PlaybackParameters parameters) { | ||||||
|   | |||||||
| @@ -212,7 +212,6 @@ public abstract class VideoPlayer extends BasePlayer | |||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void initListeners() { |     public void initListeners() { | ||||||
|         super.initListeners(); |  | ||||||
|         playbackSeekBar.setOnSeekBarChangeListener(this); |         playbackSeekBar.setOnSeekBarChangeListener(this); | ||||||
|         playbackSpeedTextView.setOnClickListener(this); |         playbackSpeedTextView.setOnClickListener(this); | ||||||
|         qualityTextView.setOnClickListener(this); |         qualityTextView.setOnClickListener(this); | ||||||
| @@ -306,9 +305,9 @@ public abstract class VideoPlayer extends BasePlayer | |||||||
|             captionItem.setOnMenuItemClickListener(menuItem -> { |             captionItem.setOnMenuItemClickListener(menuItem -> { | ||||||
|                 final int textRendererIndex = getRendererIndex(C.TRACK_TYPE_TEXT); |                 final int textRendererIndex = getRendererIndex(C.TRACK_TYPE_TEXT); | ||||||
|                 if (textRendererIndex != RENDERER_UNAVAILABLE) { |                 if (textRendererIndex != RENDERER_UNAVAILABLE) { | ||||||
|                     trackSelector.setPreferredTextLanguage(captionLanguage); |  | ||||||
|                     trackSelector.setParameters(trackSelector.buildUponParameters() |                     trackSelector.setParameters(trackSelector.buildUponParameters() | ||||||
|                             .setRendererDisabled(textRendererIndex, false)); |                             .setRendererDisabled(textRendererIndex, false) | ||||||
|  |                             .setPreferredTextLanguage(captionLanguage)); | ||||||
|                 } |                 } | ||||||
|                 return true; |                 return true; | ||||||
|             }); |             }); | ||||||
| @@ -509,12 +508,12 @@ public abstract class VideoPlayer extends BasePlayer | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         // Normalize mismatching language strings |         // Normalize mismatching language strings | ||||||
|         final String preferredLanguage = trackSelector.getPreferredTextLanguage(); |         final String preferredLanguage = trackSelector.getParameters().preferredTextLanguage; | ||||||
|  |  | ||||||
|         // Build UI |         // Build UI | ||||||
|         buildCaptionMenu(availableLanguages); |         buildCaptionMenu(availableLanguages); | ||||||
|         if (trackSelector.getParameters().getRendererDisabled(textRenderer) || |         if (trackSelector.getParameters().getRendererDisabled(textRenderer) || | ||||||
|                 preferredLanguage == null || !availableLanguages.contains(preferredLanguage)) { |                 preferredLanguage == null || (!availableLanguages.contains(preferredLanguage) | ||||||
|  |                 && !containsCaseInsensitive(availableLanguages, preferredLanguage))) { | ||||||
|             captionTextView.setText(R.string.caption_none); |             captionTextView.setText(R.string.caption_none); | ||||||
|         } else { |         } else { | ||||||
|             captionTextView.setText(preferredLanguage); |             captionTextView.setText(preferredLanguage); | ||||||
| @@ -522,6 +521,15 @@ public abstract class VideoPlayer extends BasePlayer | |||||||
|         captionTextView.setVisibility(availableLanguages.isEmpty() ? View.GONE : View.VISIBLE); |         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<String> list, String toFind) { | ||||||
|  |         for(String i : list){ | ||||||
|  |             if(i.equalsIgnoreCase(toFind)) | ||||||
|  |                 return true; | ||||||
|  |         } | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /*////////////////////////////////////////////////////////////////////////// |     /*////////////////////////////////////////////////////////////////////////// | ||||||
|     // General Player |     // General Player | ||||||
|     //////////////////////////////////////////////////////////////////////////*/ |     //////////////////////////////////////////////////////////////////////////*/ | ||||||
|   | |||||||
| @@ -12,13 +12,11 @@ import android.os.Build; | |||||||
| import android.support.annotation.NonNull; | import android.support.annotation.NonNull; | ||||||
| import android.util.Log; | import android.util.Log; | ||||||
|  |  | ||||||
| import com.google.android.exoplayer2.Format; |  | ||||||
| import com.google.android.exoplayer2.SimpleExoPlayer; | import com.google.android.exoplayer2.SimpleExoPlayer; | ||||||
| import com.google.android.exoplayer2.audio.AudioRendererEventListener; | import com.google.android.exoplayer2.analytics.AnalyticsListener; | ||||||
| import com.google.android.exoplayer2.decoder.DecoderCounters; |  | ||||||
|  |  | ||||||
| public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, | public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, | ||||||
|         AudioRendererEventListener { |         AnalyticsListener { | ||||||
|  |  | ||||||
|     private static final String TAG = "AudioFocusReactor"; |     private static final String TAG = "AudioFocusReactor"; | ||||||
|  |  | ||||||
| @@ -42,7 +40,7 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, | |||||||
|         this.player = player; |         this.player = player; | ||||||
|         this.context = context; |         this.context = context; | ||||||
|         this.audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); |         this.audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); | ||||||
|         player.addAudioDebugListener(this); |         player.addAnalyticsListener(this); | ||||||
|  |  | ||||||
|         if (SHOULD_BUILD_FOCUS_REQUEST) { |         if (SHOULD_BUILD_FOCUS_REQUEST) { | ||||||
|             request = new AudioFocusRequest.Builder(FOCUS_GAIN_TYPE) |             request = new AudioFocusRequest.Builder(FOCUS_GAIN_TYPE) | ||||||
| @@ -57,7 +55,7 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, | |||||||
|  |  | ||||||
|     public void dispose() { |     public void dispose() { | ||||||
|         abandonAudioFocus(); |         abandonAudioFocus(); | ||||||
|         player.removeAudioDebugListener(this); |         player.removeAnalyticsListener(this); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /*////////////////////////////////////////////////////////////////////////// |     /*////////////////////////////////////////////////////////////////////////// | ||||||
| @@ -164,29 +162,12 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, | |||||||
|     //////////////////////////////////////////////////////////////////////////*/ |     //////////////////////////////////////////////////////////////////////////*/ | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void onAudioSessionId(int i) { |     public void onAudioSessionId(EventTime eventTime, int audioSessionId) { | ||||||
|         if (!PlayerHelper.isUsingDSP(context)) return; |         if (!PlayerHelper.isUsingDSP(context)) return; | ||||||
|  |  | ||||||
|         final Intent intent = new Intent(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION); |         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()); |         intent.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, context.getPackageName()); | ||||||
|         context.sendBroadcast(intent); |         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) {} |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -33,14 +33,14 @@ import java.io.File; | |||||||
|  |  | ||||||
|     public CacheFactory(@NonNull final Context context, |     public CacheFactory(@NonNull final Context context, | ||||||
|                         @NonNull final String userAgent, |                         @NonNull final String userAgent, | ||||||
|                         @NonNull final TransferListener<? super DataSource> transferListener) { |                         @NonNull final TransferListener transferListener) { | ||||||
|         this(context, userAgent, transferListener, PlayerHelper.getPreferredCacheSize(context), |         this(context, userAgent, transferListener, PlayerHelper.getPreferredCacheSize(context), | ||||||
|                 PlayerHelper.getPreferredFileSize(context)); |                 PlayerHelper.getPreferredFileSize(context)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private CacheFactory(@NonNull final Context context, |     private CacheFactory(@NonNull final Context context, | ||||||
|                          @NonNull final String userAgent, |                          @NonNull final String userAgent, | ||||||
|                          @NonNull final TransferListener<? super DataSource> transferListener, |                          @NonNull final TransferListener transferListener, | ||||||
|                          final long maxCacheSize, |                          final long maxCacheSize, | ||||||
|                          final long maxFileSize) { |                          final long maxFileSize) { | ||||||
|         this.maxFileSize = maxFileSize; |         this.maxFileSize = maxFileSize; | ||||||
|   | |||||||
| @@ -2,17 +2,12 @@ package org.schabi.newpipe.player.helper; | |||||||
|  |  | ||||||
| import android.content.Context; | import android.content.Context; | ||||||
|  |  | ||||||
| import com.google.android.exoplayer2.C; |  | ||||||
| import com.google.android.exoplayer2.DefaultLoadControl; | import com.google.android.exoplayer2.DefaultLoadControl; | ||||||
| import com.google.android.exoplayer2.LoadControl; | import com.google.android.exoplayer2.LoadControl; | ||||||
| import com.google.android.exoplayer2.Renderer; | import com.google.android.exoplayer2.Renderer; | ||||||
| import com.google.android.exoplayer2.source.TrackGroupArray; | import com.google.android.exoplayer2.source.TrackGroupArray; | ||||||
| import com.google.android.exoplayer2.trackselection.TrackSelectionArray; | import com.google.android.exoplayer2.trackselection.TrackSelectionArray; | ||||||
| import com.google.android.exoplayer2.upstream.Allocator; | 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 { | public class LoadController implements LoadControl { | ||||||
|  |  | ||||||
| @@ -36,15 +31,10 @@ public class LoadController implements LoadControl { | |||||||
|                            final int optimalPlaybackBufferMs) { |                            final int optimalPlaybackBufferMs) { | ||||||
|         this.initialPlaybackBufferUs = initialPlaybackBufferMs * 1000; |         this.initialPlaybackBufferUs = initialPlaybackBufferMs * 1000; | ||||||
|  |  | ||||||
|         final DefaultAllocator allocator = new DefaultAllocator(true, |         DefaultLoadControl.Builder builder = new DefaultLoadControl.Builder(); | ||||||
|                 C.DEFAULT_BUFFER_SEGMENT_SIZE); |         builder.setBufferDurationsMs(minimumPlaybackbufferMs, optimalPlaybackBufferMs, | ||||||
|  |                 initialPlaybackBufferMs, initialPlaybackBufferMs); | ||||||
|         internalLoadControl = new DefaultLoadControl(allocator, |         internalLoadControl = builder.createDefaultLoadControl(); | ||||||
|                 /*minBufferMs=*/minimumPlaybackbufferMs, |  | ||||||
|                 /*maxBufferMs=*/optimalPlaybackBufferMs, |  | ||||||
|                 /*bufferForPlaybackMs=*/initialPlaybackBufferMs, |  | ||||||
|                 /*bufferForPlaybackAfterRebufferMs=*/initialPlaybackBufferMs, |  | ||||||
|                 DEFAULT_TARGET_BUFFER_BYTES, DEFAULT_PRIORITIZE_TIME_OVER_SIZE_THRESHOLDS); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /*////////////////////////////////////////////////////////////////////////// |     /*////////////////////////////////////////////////////////////////////////// | ||||||
|   | |||||||
| @@ -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.source.smoothstreaming.SsMediaSource; | ||||||
| import com.google.android.exoplayer2.upstream.DataSource; | import com.google.android.exoplayer2.upstream.DataSource; | ||||||
| import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; | import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; | ||||||
|  | import com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy; | ||||||
| import com.google.android.exoplayer2.upstream.TransferListener; | import com.google.android.exoplayer2.upstream.TransferListener; | ||||||
|  |  | ||||||
| public class PlayerDataSource { | public class PlayerDataSource { | ||||||
| @@ -24,7 +25,7 @@ public class PlayerDataSource { | |||||||
|  |  | ||||||
|     public PlayerDataSource(@NonNull final Context context, |     public PlayerDataSource(@NonNull final Context context, | ||||||
|                             @NonNull final String userAgent, |                             @NonNull final String userAgent, | ||||||
|                             @NonNull final TransferListener<? super DataSource> transferListener) { |                             @NonNull final TransferListener transferListener) { | ||||||
|         cacheDataSourceFactory = new CacheFactory(context, userAgent, transferListener); |         cacheDataSourceFactory = new CacheFactory(context, userAgent, transferListener); | ||||||
|         cachelessDataSourceFactory = new DefaultDataSourceFactory(context, userAgent, transferListener); |         cachelessDataSourceFactory = new DefaultDataSourceFactory(context, userAgent, transferListener); | ||||||
|     } |     } | ||||||
| @@ -32,21 +33,21 @@ public class PlayerDataSource { | |||||||
|     public SsMediaSource.Factory getLiveSsMediaSourceFactory() { |     public SsMediaSource.Factory getLiveSsMediaSourceFactory() { | ||||||
|         return new SsMediaSource.Factory(new DefaultSsChunkSource.Factory( |         return new SsMediaSource.Factory(new DefaultSsChunkSource.Factory( | ||||||
|                 cachelessDataSourceFactory), cachelessDataSourceFactory) |                 cachelessDataSourceFactory), cachelessDataSourceFactory) | ||||||
|                 .setMinLoadableRetryCount(MANIFEST_MINIMUM_RETRY) |                 .setLoadErrorHandlingPolicy(new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY)) | ||||||
|                 .setLivePresentationDelayMs(LIVE_STREAM_EDGE_GAP_MILLIS); |                 .setLivePresentationDelayMs(LIVE_STREAM_EDGE_GAP_MILLIS); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public HlsMediaSource.Factory getLiveHlsMediaSourceFactory() { |     public HlsMediaSource.Factory getLiveHlsMediaSourceFactory() { | ||||||
|         return new HlsMediaSource.Factory(cachelessDataSourceFactory) |         return new HlsMediaSource.Factory(cachelessDataSourceFactory) | ||||||
|                 .setAllowChunklessPreparation(true) |                 .setAllowChunklessPreparation(true) | ||||||
|                 .setMinLoadableRetryCount(MANIFEST_MINIMUM_RETRY); |                 .setLoadErrorHandlingPolicy(new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public DashMediaSource.Factory getLiveDashMediaSourceFactory() { |     public DashMediaSource.Factory getLiveDashMediaSourceFactory() { | ||||||
|         return new DashMediaSource.Factory(new DefaultDashChunkSource.Factory( |         return new DashMediaSource.Factory(new DefaultDashChunkSource.Factory( | ||||||
|                 cachelessDataSourceFactory), cachelessDataSourceFactory) |                 cachelessDataSourceFactory), cachelessDataSourceFactory) | ||||||
|                 .setMinLoadableRetryCount(MANIFEST_MINIMUM_RETRY) |                 .setLoadErrorHandlingPolicy(new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY)) | ||||||
|                 .setLivePresentationDelayMs(LIVE_STREAM_EDGE_GAP_MILLIS); |                 .setLivePresentationDelayMs(LIVE_STREAM_EDGE_GAP_MILLIS, true); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public SsMediaSource.Factory getSsMediaSourceFactory() { |     public SsMediaSource.Factory getSsMediaSourceFactory() { | ||||||
| @@ -65,7 +66,7 @@ public class PlayerDataSource { | |||||||
|  |  | ||||||
|     public ExtractorMediaSource.Factory getExtractorMediaSourceFactory() { |     public ExtractorMediaSource.Factory getExtractorMediaSourceFactory() { | ||||||
|         return new ExtractorMediaSource.Factory(cacheDataSourceFactory) |         return new ExtractorMediaSource.Factory(cacheDataSourceFactory) | ||||||
|                 .setMinLoadableRetryCount(EXTRACTOR_MINIMUM_RETRY); |                 .setLoadErrorHandlingPolicy(new DefaultLoadErrorHandlingPolicy(EXTRACTOR_MINIMUM_RETRY)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public ExtractorMediaSource.Factory getExtractorMediaSourceFactory(@NonNull final String key) { |     public ExtractorMediaSource.Factory getExtractorMediaSourceFactory(@NonNull final String key) { | ||||||
|   | |||||||
| @@ -14,7 +14,6 @@ import com.google.android.exoplayer2.text.CaptionStyleCompat; | |||||||
| import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection; | import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection; | ||||||
| import com.google.android.exoplayer2.trackselection.TrackSelection; | import com.google.android.exoplayer2.trackselection.TrackSelection; | ||||||
| import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; | import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; | ||||||
| import com.google.android.exoplayer2.upstream.BandwidthMeter; |  | ||||||
| import com.google.android.exoplayer2.util.MimeTypes; | import com.google.android.exoplayer2.util.MimeTypes; | ||||||
|  |  | ||||||
| import org.schabi.newpipe.R; | import org.schabi.newpipe.R; | ||||||
| @@ -240,9 +239,8 @@ public class PlayerHelper { | |||||||
|         return 60000; |         return 60000; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static TrackSelection.Factory getQualitySelector(@NonNull final Context context, |     public static TrackSelection.Factory getQualitySelector(@NonNull final Context context) { | ||||||
|                                                             @NonNull final BandwidthMeter meter) { |         return new AdaptiveTrackSelection.Factory( | ||||||
|         return new AdaptiveTrackSelection.Factory(meter, |  | ||||||
|                 /*bufferDurationRequiredForQualityIncrease=*/1000, |                 /*bufferDurationRequiredForQualityIncrease=*/1000, | ||||||
|                 AdaptiveTrackSelection.DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS, |                 AdaptiveTrackSelection.DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS, | ||||||
|                 AdaptiveTrackSelection.DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS, |                 AdaptiveTrackSelection.DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS, | ||||||
|   | |||||||
| @@ -1,12 +1,13 @@ | |||||||
| package org.schabi.newpipe.player.mediasource; | package org.schabi.newpipe.player.mediasource; | ||||||
|  |  | ||||||
| import android.support.annotation.NonNull; | import android.support.annotation.NonNull; | ||||||
|  | import android.support.annotation.Nullable; | ||||||
| import android.util.Log; | import android.util.Log; | ||||||
|  |  | ||||||
| import com.google.android.exoplayer2.ExoPlayer; |  | ||||||
| import com.google.android.exoplayer2.source.BaseMediaSource; | import com.google.android.exoplayer2.source.BaseMediaSource; | ||||||
| import com.google.android.exoplayer2.source.MediaPeriod; | import com.google.android.exoplayer2.source.MediaPeriod; | ||||||
| import com.google.android.exoplayer2.upstream.Allocator; | import com.google.android.exoplayer2.upstream.Allocator; | ||||||
|  | import com.google.android.exoplayer2.upstream.TransferListener; | ||||||
|  |  | ||||||
| import org.schabi.newpipe.player.playqueue.PlayQueueItem; | import org.schabi.newpipe.player.playqueue.PlayQueueItem; | ||||||
|  |  | ||||||
| @@ -79,7 +80,7 @@ public class FailedMediaSource extends BaseMediaSource implements ManagedMediaSo | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) { |     public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) { | ||||||
|         return null; |         return null; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -88,7 +89,7 @@ public class FailedMediaSource extends BaseMediaSource implements ManagedMediaSo | |||||||
|  |  | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     protected void prepareSourceInternal(ExoPlayer player, boolean isTopLevelSource) { |     protected void prepareSourceInternal(@Nullable TransferListener mediaTransferListener) { | ||||||
|         Log.e(TAG, "Loading failed source: ", error); |         Log.e(TAG, "Loading failed source: ", error); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,12 +2,13 @@ package org.schabi.newpipe.player.mediasource; | |||||||
|  |  | ||||||
| import android.os.Handler; | import android.os.Handler; | ||||||
| import android.support.annotation.NonNull; | 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.MediaPeriod; | ||||||
| import com.google.android.exoplayer2.source.MediaSource; | import com.google.android.exoplayer2.source.MediaSource; | ||||||
| import com.google.android.exoplayer2.source.MediaSourceEventListener; | import com.google.android.exoplayer2.source.MediaSourceEventListener; | ||||||
| import com.google.android.exoplayer2.upstream.Allocator; | import com.google.android.exoplayer2.upstream.Allocator; | ||||||
|  | import com.google.android.exoplayer2.upstream.TransferListener; | ||||||
|  |  | ||||||
| import org.schabi.newpipe.player.playqueue.PlayQueueItem; | import org.schabi.newpipe.player.playqueue.PlayQueueItem; | ||||||
|  |  | ||||||
| @@ -36,9 +37,8 @@ public class LoadedMediaSource implements ManagedMediaSource { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void prepareSource(ExoPlayer player, boolean isTopLevelSource, |     public void prepareSource(SourceInfoRefreshListener listener, @Nullable TransferListener mediaTransferListener) { | ||||||
|                               SourceInfoRefreshListener listener) { |         source.prepareSource(listener, mediaTransferListener); | ||||||
|         source.prepareSource(player, isTopLevelSource, listener); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
| @@ -47,8 +47,8 @@ public class LoadedMediaSource implements ManagedMediaSource { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) { |     public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) { | ||||||
|         return source.createPeriod(id, allocator); |         return source.createPeriod(id, allocator, startPositionUs); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| package org.schabi.newpipe.player.mediasource; | package org.schabi.newpipe.player.mediasource; | ||||||
|  | import android.os.Handler; | ||||||
| import android.support.annotation.NonNull; | import android.support.annotation.NonNull; | ||||||
| import android.support.annotation.Nullable; | import android.support.annotation.Nullable; | ||||||
|  |  | ||||||
| @@ -86,21 +86,22 @@ public class ManagedMediaSourcePlaylist { | |||||||
|     /** |     /** | ||||||
|      * Invalidates the {@link ManagedMediaSource} at the given index by replacing it |      * Invalidates the {@link ManagedMediaSource} at the given index by replacing it | ||||||
|      * with a {@link PlaceholderMediaSource}. |      * with a {@link PlaceholderMediaSource}. | ||||||
|      * @see #update(int, ManagedMediaSource, Runnable) |      * @see #update(int, ManagedMediaSource, Handler, Runnable) | ||||||
|      * */ |      * */ | ||||||
|     public synchronized void invalidate(final int index, |     public synchronized void invalidate(final int index, | ||||||
|  |                                         @Nullable final Handler handler, | ||||||
|                                         @Nullable final Runnable finalizingAction) { |                                         @Nullable final Runnable finalizingAction) { | ||||||
|         if (get(index) instanceof PlaceholderMediaSource) return; |         if (get(index) instanceof PlaceholderMediaSource) return; | ||||||
|         update(index, new PlaceholderMediaSource(), finalizingAction); |         update(index, new PlaceholderMediaSource(), handler, finalizingAction); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Updates the {@link ManagedMediaSource} in {@link ConcatenatingMediaSource} |      * Updates the {@link ManagedMediaSource} in {@link ConcatenatingMediaSource} | ||||||
|      * at the given index with a given {@link ManagedMediaSource}. |      * 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) { |     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, |      * at the given index with a given {@link ManagedMediaSource}. If the index is out of bound, | ||||||
|      * then the replacement is ignored. |      * then the replacement is ignored. | ||||||
|      * @see ConcatenatingMediaSource#addMediaSource |      * @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, |     public synchronized void update(final int index, @NonNull final ManagedMediaSource source, | ||||||
|  |                                     @Nullable final Handler handler, | ||||||
|                                     @Nullable final Runnable finalizingAction) { |                                     @Nullable final Runnable finalizingAction) { | ||||||
|         if (index < 0 || index >= internalSource.getSize()) return; |         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 |         // 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. |         // in the finalizing action AFTER the removal is complete and the timeline has changed. | ||||||
|         internalSource.removeMediaSource(index, finalizingAction); |         internalSource.removeMediaSource(index, handler, finalizingAction); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,20 +1,21 @@ | |||||||
| package org.schabi.newpipe.player.mediasource; | package org.schabi.newpipe.player.mediasource; | ||||||
|  |  | ||||||
| import android.support.annotation.NonNull; | 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.BaseMediaSource; | ||||||
| import com.google.android.exoplayer2.source.MediaPeriod; | import com.google.android.exoplayer2.source.MediaPeriod; | ||||||
| import com.google.android.exoplayer2.upstream.Allocator; | import com.google.android.exoplayer2.upstream.Allocator; | ||||||
|  | import com.google.android.exoplayer2.upstream.TransferListener; | ||||||
|  |  | ||||||
| import org.schabi.newpipe.player.playqueue.PlayQueueItem; | import org.schabi.newpipe.player.playqueue.PlayQueueItem; | ||||||
|  |  | ||||||
| public class PlaceholderMediaSource extends BaseMediaSource implements ManagedMediaSource { | public class PlaceholderMediaSource extends BaseMediaSource implements ManagedMediaSource { | ||||||
|     // Do nothing, so this will stall the playback |     // Do nothing, so this will stall the playback | ||||||
|     @Override public void maybeThrowSourceInfoRefreshError() {} |     @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 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 protected void releaseSourceInternal() {} | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|   | |||||||
| @@ -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); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,5 +1,5 @@ | |||||||
| package org.schabi.newpipe.player.playback; | package org.schabi.newpipe.player.playback; | ||||||
|  | import android.os.Handler; | ||||||
| import android.support.annotation.NonNull; | import android.support.annotation.NonNull; | ||||||
| import android.support.annotation.Nullable; | import android.support.annotation.Nullable; | ||||||
| import android.support.v4.util.ArraySet; | import android.support.v4.util.ArraySet; | ||||||
| @@ -103,6 +103,8 @@ public class MediaSourceManager { | |||||||
|  |  | ||||||
|     @NonNull private ManagedMediaSourcePlaylist playlist; |     @NonNull private ManagedMediaSourcePlaylist playlist; | ||||||
|  |  | ||||||
|  |     private Handler removeMediaSourceHandler = new Handler(); | ||||||
|  |  | ||||||
|     public MediaSourceManager(@NonNull final PlaybackListener listener, |     public MediaSourceManager(@NonNull final PlaybackListener listener, | ||||||
|                               @NonNull final PlayQueue playQueue) { |                               @NonNull final PlayQueue playQueue) { | ||||||
|         this(listener, playQueue, /*loadDebounceMillis=*/400L, |         this(listener, playQueue, /*loadDebounceMillis=*/400L, | ||||||
| @@ -395,7 +397,7 @@ public class MediaSourceManager { | |||||||
|         if (isCorrectionNeeded(item)) { |         if (isCorrectionNeeded(item)) { | ||||||
|             if (DEBUG) Log.d(TAG, "MediaSource - Updating index=[" + itemIndex + "] with " + |             if (DEBUG) Log.d(TAG, "MediaSource - Updating index=[" + itemIndex + "] with " + | ||||||
|                     "title=[" + item.getTitle() + "] at url=[" + item.getUrl() + "]"); |                     "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, " + |         if (DEBUG) Log.d(TAG, "MediaSource - Reloading currently playing, " + | ||||||
|                 "index=[" + currentIndex + "], item=[" + currentItem.getTitle() + "]"); |                 "index=[" + currentIndex + "], item=[" + currentItem.getTitle() + "]"); | ||||||
|         playlist.invalidate(currentIndex, this::loadImmediate); |         playlist.invalidate(currentIndex, removeMediaSourceHandler, this::loadImmediate); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void maybeClearLoaders() { |     private void maybeClearLoaders() { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Ritvik Saraf
					Ritvik Saraf