Merge pull request #2184 from Redirion/exoplayerupdate
Update ExoPlayer to 2.9.6
This commit is contained in:
commit
6651aa924f
17 changed files with 74 additions and 217 deletions
|
@ -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() {
|
||||||
|
|
Loading…
Reference in a new issue