mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-31 15:23:00 +00:00 
			
		
		
		
	Merge remote-tracking branch 'upstream/dev' into defaultTrending
This commit is contained in:
		| @@ -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' | ||||
| } | ||||
|   | ||||
| @@ -47,7 +47,7 @@ public class DownloadActivity extends AppCompatActivity { | ||||
|             @Override | ||||
|             public void onGlobalLayout() { | ||||
|                 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.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)); | ||||
|   | ||||
| @@ -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); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private boolean isInMultiWindow() { | ||||
|   | ||||
| @@ -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); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private void onPlaybackParameterChanged(final PlaybackParameters parameters) { | ||||
|   | ||||
| @@ -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<String> list, String toFind) { | ||||
|         for(String i : list){ | ||||
|             if(i.equalsIgnoreCase(toFind)) | ||||
|                 return true; | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     /*////////////////////////////////////////////////////////////////////////// | ||||
|     // General Player | ||||
|     //////////////////////////////////////////////////////////////////////////*/ | ||||
|   | ||||
| @@ -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) {} | ||||
| } | ||||
|   | ||||
| @@ -33,14 +33,14 @@ import java.io.File; | ||||
|  | ||||
|     public CacheFactory(@NonNull final Context context, | ||||
|                         @NonNull final String userAgent, | ||||
|                         @NonNull final TransferListener<? super DataSource> 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<? super DataSource> transferListener, | ||||
|                          @NonNull final TransferListener transferListener, | ||||
|                          final long maxCacheSize, | ||||
|                          final long maxFileSize) { | ||||
|         this.maxFileSize = maxFileSize; | ||||
|   | ||||
| @@ -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(); | ||||
|     } | ||||
|  | ||||
|     /*////////////////////////////////////////////////////////////////////////// | ||||
|   | ||||
| @@ -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<? super DataSource> 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) { | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
| @@ -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); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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; | ||||
|  | ||||
| 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() { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Ritvik Saraf
					Ritvik Saraf