1
0
mirror of https://github.com/TeamNewPipe/NewPipe.git synced 2024-11-25 04:22:30 +01:00

Merge pull request #7005 from Redirion/exo14

Update ExoPlayer to 2.14.2
This commit is contained in:
Robin 2021-11-12 20:19:00 +01:00 committed by GitHub
commit dfba10f8ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 152 additions and 101 deletions

View File

@ -105,7 +105,7 @@ ext {
androidxRoomVersion = '2.3.0' androidxRoomVersion = '2.3.0'
icepickVersion = '3.2.0' icepickVersion = '3.2.0'
exoPlayerVersion = '2.12.3' exoPlayerVersion = '2.14.2'
googleAutoServiceVersion = '1.0' googleAutoServiceVersion = '1.0'
groupieVersion = '2.10.0' groupieVersion = '2.10.0'
markwonVersion = '4.6.2' markwonVersion = '4.6.2'

View File

@ -1,12 +1,13 @@
package org.schabi.newpipe.player; package org.schabi.newpipe.player;
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_AD_INSERTION; import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_AUTO_TRANSITION;
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_INTERNAL; import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_INTERNAL;
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_PERIOD_TRANSITION; import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_REMOVE;
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_SEEK; import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_SEEK;
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT; import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT;
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_SKIP;
import static com.google.android.exoplayer2.Player.DiscontinuityReason; import static com.google.android.exoplayer2.Player.DiscontinuityReason;
import static com.google.android.exoplayer2.Player.EventListener; import static com.google.android.exoplayer2.Player.Listener;
import static com.google.android.exoplayer2.Player.REPEAT_MODE_ALL; import static com.google.android.exoplayer2.Player.REPEAT_MODE_ALL;
import static com.google.android.exoplayer2.Player.REPEAT_MODE_OFF; import static com.google.android.exoplayer2.Player.REPEAT_MODE_OFF;
import static com.google.android.exoplayer2.Player.REPEAT_MODE_ONE; import static com.google.android.exoplayer2.Player.REPEAT_MODE_ONE;
@ -116,6 +117,7 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.DefaultRenderersFactory; import com.google.android.exoplayer2.DefaultRenderersFactory;
import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player.PositionInfo;
import com.google.android.exoplayer2.RenderersFactory; import com.google.android.exoplayer2.RenderersFactory;
import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
@ -123,13 +125,14 @@ 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.TrackGroup; import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.text.CaptionStyleCompat; import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray; import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
import com.google.android.exoplayer2.ui.CaptionStyleCompat;
import com.google.android.exoplayer2.ui.SubtitleView; import com.google.android.exoplayer2.ui.SubtitleView;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.VideoListener; import com.google.android.exoplayer2.video.VideoSize;
import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.squareup.picasso.Picasso; import com.squareup.picasso.Picasso;
import com.squareup.picasso.Target; import com.squareup.picasso.Target;
@ -174,12 +177,12 @@ import org.schabi.newpipe.player.resolver.MediaSourceTag;
import org.schabi.newpipe.player.resolver.VideoPlaybackResolver; import org.schabi.newpipe.player.resolver.VideoPlaybackResolver;
import org.schabi.newpipe.player.seekbarpreview.SeekbarPreviewThumbnailHelper; import org.schabi.newpipe.player.seekbarpreview.SeekbarPreviewThumbnailHelper;
import org.schabi.newpipe.player.seekbarpreview.SeekbarPreviewThumbnailHolder; import org.schabi.newpipe.player.seekbarpreview.SeekbarPreviewThumbnailHolder;
import org.schabi.newpipe.util.StreamTypeUtil;
import org.schabi.newpipe.util.DeviceUtils; import org.schabi.newpipe.util.DeviceUtils;
import org.schabi.newpipe.util.ListHelper; import org.schabi.newpipe.util.ListHelper;
import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.PicassoHelper; import org.schabi.newpipe.util.PicassoHelper;
import org.schabi.newpipe.util.SerializedCache; import org.schabi.newpipe.util.SerializedCache;
import org.schabi.newpipe.util.StreamTypeUtil;
import org.schabi.newpipe.util.external_communication.KoreUtils; import org.schabi.newpipe.util.external_communication.KoreUtils;
import org.schabi.newpipe.util.external_communication.ShareUtils; import org.schabi.newpipe.util.external_communication.ShareUtils;
import org.schabi.newpipe.views.ExpandableSurfaceView; import org.schabi.newpipe.views.ExpandableSurfaceView;
@ -197,9 +200,8 @@ import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.disposables.SerialDisposable; import io.reactivex.rxjava3.disposables.SerialDisposable;
public final class Player implements public final class Player implements
EventListener,
PlaybackListener, PlaybackListener,
VideoListener, Listener,
SeekBar.OnSeekBarChangeListener, SeekBar.OnSeekBarChangeListener,
View.OnClickListener, View.OnClickListener,
PopupMenu.OnMenuItemClickListener, PopupMenu.OnMenuItemClickListener,
@ -501,10 +503,6 @@ public final class Player implements
// Setup video view // Setup video view
setupVideoSurface(); setupVideoSurface();
simpleExoPlayer.addVideoListener(this);
// Setup subtitle view
simpleExoPlayer.addTextOutput(binding.subtitleView);
// enable media tunneling // enable media tunneling
if (DEBUG && PreferenceManager.getDefaultSharedPreferences(context) if (DEBUG && PreferenceManager.getDefaultSharedPreferences(context)
@ -513,7 +511,7 @@ public final class Player implements
+ "media tunneling disabled in debug preferences"); + "media tunneling disabled in debug preferences");
} else if (DeviceUtils.shouldSupportMediaTunneling()) { } else if (DeviceUtils.shouldSupportMediaTunneling()) {
trackSelector.setParameters(trackSelector.buildUponParameters() trackSelector.setParameters(trackSelector.buildUponParameters()
.setTunnelingAudioSessionId(C.generateAudioSessionIdV21(context))); .setTunnelingEnabled(true));
} else if (DEBUG) { } else if (DEBUG) {
Log.d(TAG, "[" + Util.DEVICE_DEBUG_INFO + "] does not support media tunneling"); Log.d(TAG, "[" + Util.DEVICE_DEBUG_INFO + "] does not support media tunneling");
} }
@ -809,7 +807,6 @@ public final class Player implements
if (!exoPlayerIsNull()) { if (!exoPlayerIsNull()) {
simpleExoPlayer.removeListener(this); simpleExoPlayer.removeListener(this);
simpleExoPlayer.removeVideoListener(this);
simpleExoPlayer.stop(); simpleExoPlayer.stop();
simpleExoPlayer.release(); simpleExoPlayer.release();
} }
@ -898,7 +895,7 @@ public final class Player implements
public void smoothStopPlayer() { public void smoothStopPlayer() {
// Pausing would make transition from one stream to a new stream not smooth, so only stop // Pausing would make transition from one stream to a new stream not smooth, so only stop
simpleExoPlayer.stop(false); simpleExoPlayer.stop();
} }
//endregion //endregion
@ -2437,7 +2434,9 @@ public final class Player implements
} }
@Override @Override
public void onPositionDiscontinuity(@DiscontinuityReason final int discontinuityReason) { public void onPositionDiscontinuity(
final PositionInfo oldPosition, final PositionInfo newPosition,
@DiscontinuityReason final int discontinuityReason) {
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "ExoPlayer - onPositionDiscontinuity() called with " Log.d(TAG, "ExoPlayer - onPositionDiscontinuity() called with "
+ "discontinuityReason = [" + discontinuityReason + "]"); + "discontinuityReason = [" + discontinuityReason + "]");
@ -2449,7 +2448,7 @@ public final class Player implements
// Refresh the playback if there is a transition to the next video // Refresh the playback if there is a transition to the next video
final int newWindowIndex = simpleExoPlayer.getCurrentWindowIndex(); final int newWindowIndex = simpleExoPlayer.getCurrentWindowIndex();
switch (discontinuityReason) { switch (discontinuityReason) {
case DISCONTINUITY_REASON_PERIOD_TRANSITION: case DISCONTINUITY_REASON_REMOVE:
// When player is in single repeat mode and a period transition occurs, // When player is in single repeat mode and a period transition occurs,
// we need to register a view count here since no metadata has changed // we need to register a view count here since no metadata has changed
if (getRepeatMode() == REPEAT_MODE_ONE && newWindowIndex == playQueue.getIndex()) { if (getRepeatMode() == REPEAT_MODE_ONE && newWindowIndex == playQueue.getIndex()) {
@ -2470,7 +2469,8 @@ public final class Player implements
playQueue.setIndex(newWindowIndex); playQueue.setIndex(newWindowIndex);
} }
break; break;
case DISCONTINUITY_REASON_AD_INSERTION: case DISCONTINUITY_REASON_SKIP:
case DISCONTINUITY_REASON_AUTO_TRANSITION:
break; // only makes Android Studio linter happy, as there are no ads break; // only makes Android Studio linter happy, as there are no ads
} }
@ -2482,6 +2482,11 @@ public final class Player implements
//TODO check if this causes black screen when switching to fullscreen //TODO check if this causes black screen when switching to fullscreen
animate(binding.surfaceForeground, false, DEFAULT_CONTROLS_DURATION); animate(binding.surfaceForeground, false, DEFAULT_CONTROLS_DURATION);
} }
@Override
public void onCues(final List<Cue> cues) {
binding.subtitleView.onCues(cues);
}
//endregion //endregion
@ -2503,7 +2508,7 @@ public final class Player implements
* </ul> * </ul>
* *
* @see #processSourceError(IOException) * @see #processSourceError(IOException)
* @see com.google.android.exoplayer2.Player.EventListener#onPlayerError(ExoPlaybackException) * @see com.google.android.exoplayer2.Player.Listener#onPlayerError(ExoPlaybackException)
*/ */
@Override @Override
public void onPlayerError(@NonNull final ExoPlaybackException error) { public void onPlayerError(@NonNull final ExoPlaybackException error) {
@ -3867,19 +3872,17 @@ public final class Player implements
} }
@Override // exoplayer listener @Override // exoplayer listener
public void onVideoSizeChanged(final int width, final int height, public void onVideoSizeChanged(final VideoSize videoSize) {
final int unappliedRotationDegrees,
final float pixelWidthHeightRatio) {
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "onVideoSizeChanged() called with: " Log.d(TAG, "onVideoSizeChanged() called with: "
+ "width / height = [" + width + " / " + height + "width / height = [" + videoSize.width + " / " + videoSize.height
+ " = " + (((float) width) / height) + "], " + " = " + (((float) videoSize.width) / videoSize.height) + "], "
+ "unappliedRotationDegrees = [" + unappliedRotationDegrees + "], " + "unappliedRotationDegrees = [" + videoSize.unappliedRotationDegrees + "], "
+ "pixelWidthHeightRatio = [" + pixelWidthHeightRatio + "]"); + "pixelWidthHeightRatio = [" + videoSize.pixelWidthHeightRatio + "]");
} }
binding.surfaceView.setAspectRatio(((float) width) / height); binding.surfaceView.setAspectRatio(((float) videoSize.width) / videoSize.height);
isVerticalVideo = width < height; isVerticalVideo = videoSize.width < videoSize.height;
if (globalScreenOrientationLocked(context) if (globalScreenOrientationLocked(context)
&& isFullscreen && isFullscreen

View File

@ -16,7 +16,6 @@ import androidx.media.AudioManagerCompat;
import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.analytics.AnalyticsListener; import com.google.android.exoplayer2.analytics.AnalyticsListener;
import com.google.android.exoplayer2.decoder.DecoderCounters;
public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, AnalyticsListener { public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, AnalyticsListener {
@ -150,15 +149,9 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, An
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
@Override @Override
public void onAudioSessionId(final EventTime eventTime, final int audioSessionId) { public void onAudioSessionIdChanged(final EventTime eventTime, final int audioSessionId) {
notifyAudioSessionUpdate(true, audioSessionId); notifyAudioSessionUpdate(true, audioSessionId);
} }
@Override
public void onAudioDisabled(final EventTime eventTime, final DecoderCounters counters) {
notifyAudioSessionUpdate(false, player.getAudioSessionId());
}
private void notifyAudioSessionUpdate(final boolean active, final int audioSessionId) { private void notifyAudioSessionUpdate(final boolean active, final int audioSessionId) {
if (!PlayerHelper.isUsingDSP()) { if (!PlayerHelper.isUsingDSP()) {
return; return;

View File

@ -4,7 +4,7 @@ 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.ExoTrackSelection;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
public class LoadController implements LoadControl { public class LoadController implements LoadControl {
@ -47,7 +47,7 @@ public class LoadController implements LoadControl {
@Override @Override
public void onTracksSelected(final Renderer[] renderers, final TrackGroupArray trackGroups, public void onTracksSelected(final Renderer[] renderers, final TrackGroupArray trackGroups,
final TrackSelectionArray trackSelections) { final ExoTrackSelection[] trackSelections) {
internalLoadControl.onTracksSelected(renderers, trackGroups, trackSelections); internalLoadControl.onTracksSelected(renderers, trackGroups, trackSelections);
} }
@ -91,11 +91,12 @@ public class LoadController implements LoadControl {
@Override @Override
public boolean shouldStartPlayback(final long bufferedDurationUs, final float playbackSpeed, public boolean shouldStartPlayback(final long bufferedDurationUs, final float playbackSpeed,
final boolean rebuffering) { final boolean rebuffering, final long targetLiveOffsetUs) {
final boolean isInitialPlaybackBufferFilled final boolean isInitialPlaybackBufferFilled
= bufferedDurationUs >= this.initialPlaybackBufferUs * playbackSpeed; = bufferedDurationUs >= this.initialPlaybackBufferUs * playbackSpeed;
final boolean isInternalStartingPlayback = internalLoadControl final boolean isInternalStartingPlayback = internalLoadControl
.shouldStartPlayback(bufferedDurationUs, playbackSpeed, rebuffering); .shouldStartPlayback(bufferedDurationUs, playbackSpeed, rebuffering,
targetLiveOffsetUs);
return isInitialPlaybackBufferFilled || isInternalStartingPlayback; return isInitialPlaybackBufferFilled || isInternalStartingPlayback;
} }

View File

@ -1,14 +1,18 @@
package org.schabi.newpipe.player.helper; package org.schabi.newpipe.player.helper;
import android.content.Context; import android.content.Context;
import android.os.Build;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.google.android.exoplayer2.source.MediaParserExtractorAdapter;
import com.google.android.exoplayer2.source.ProgressiveMediaSource; import com.google.android.exoplayer2.source.ProgressiveMediaSource;
import com.google.android.exoplayer2.source.SingleSampleMediaSource; import com.google.android.exoplayer2.source.SingleSampleMediaSource;
import com.google.android.exoplayer2.source.chunk.MediaParserChunkExtractor;
import com.google.android.exoplayer2.source.dash.DashMediaSource; import com.google.android.exoplayer2.source.dash.DashMediaSource;
import com.google.android.exoplayer2.source.dash.DefaultDashChunkSource; import com.google.android.exoplayer2.source.dash.DefaultDashChunkSource;
import com.google.android.exoplayer2.source.hls.HlsMediaSource; import com.google.android.exoplayer2.source.hls.HlsMediaSource;
import com.google.android.exoplayer2.source.hls.MediaParserHlsMediaChunkExtractor;
import com.google.android.exoplayer2.source.smoothstreaming.DefaultSsChunkSource; 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;
@ -19,7 +23,7 @@ import com.google.android.exoplayer2.upstream.TransferListener;
public class PlayerDataSource { public class PlayerDataSource {
private static final int MANIFEST_MINIMUM_RETRY = 5; private static final int MANIFEST_MINIMUM_RETRY = 5;
private static final int EXTRACTOR_MINIMUM_RETRY = Integer.MAX_VALUE; private static final int EXTRACTOR_MINIMUM_RETRY = Integer.MAX_VALUE;
private static final int LIVE_STREAM_EDGE_GAP_MILLIS = 10000; public static final int LIVE_STREAM_EDGE_GAP_MILLIS = 10000;
private final DataSource.Factory cacheDataSourceFactory; private final DataSource.Factory cacheDataSourceFactory;
private final DataSource.Factory cachelessDataSourceFactory; private final DataSource.Factory cachelessDataSourceFactory;
@ -32,51 +36,83 @@ public class PlayerDataSource {
} }
public SsMediaSource.Factory getLiveSsMediaSourceFactory() { public SsMediaSource.Factory getLiveSsMediaSourceFactory() {
return new SsMediaSource.Factory(new DefaultSsChunkSource.Factory( return new SsMediaSource.Factory(
cachelessDataSourceFactory), cachelessDataSourceFactory) new DefaultSsChunkSource.Factory(cachelessDataSourceFactory),
cachelessDataSourceFactory
)
.setLoadErrorHandlingPolicy( .setLoadErrorHandlingPolicy(
new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY)) 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) final HlsMediaSource.Factory factory =
.setAllowChunklessPreparation(true) new HlsMediaSource.Factory(cachelessDataSourceFactory)
.setAllowChunklessPreparation(true)
.setLoadErrorHandlingPolicy(
new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
factory.setExtractorFactory(MediaParserHlsMediaChunkExtractor.FACTORY);
}
return factory;
}
public DashMediaSource.Factory getLiveDashMediaSourceFactory() {
return new DashMediaSource.Factory(
getDefaultDashChunkSourceFactory(cachelessDataSourceFactory),
cachelessDataSourceFactory
)
.setLoadErrorHandlingPolicy( .setLoadErrorHandlingPolicy(
new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY)); new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY));
} }
public DashMediaSource.Factory getLiveDashMediaSourceFactory() { private DefaultDashChunkSource.Factory getDefaultDashChunkSourceFactory(
return new DashMediaSource.Factory(new DefaultDashChunkSource.Factory( final DataSource.Factory dataSourceFactory
cachelessDataSourceFactory), cachelessDataSourceFactory) ) {
.setLoadErrorHandlingPolicy( if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY)) return new DefaultDashChunkSource.Factory(
.setLivePresentationDelayMs(LIVE_STREAM_EDGE_GAP_MILLIS, true); MediaParserChunkExtractor.FACTORY,
} dataSourceFactory,
1
);
}
public SsMediaSource.Factory getSsMediaSourceFactory() { return new DefaultDashChunkSource.Factory(dataSourceFactory);
return new SsMediaSource.Factory(new DefaultSsChunkSource.Factory(
cacheDataSourceFactory), cacheDataSourceFactory);
} }
public HlsMediaSource.Factory getHlsMediaSourceFactory() { public HlsMediaSource.Factory getHlsMediaSourceFactory() {
return new HlsMediaSource.Factory(cacheDataSourceFactory); final HlsMediaSource.Factory factory = new HlsMediaSource.Factory(cacheDataSourceFactory);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
return factory;
}
// *** >= Android 11 / R / API 30 ***
return factory.setExtractorFactory(MediaParserHlsMediaChunkExtractor.FACTORY);
} }
public DashMediaSource.Factory getDashMediaSourceFactory() { public DashMediaSource.Factory getDashMediaSourceFactory() {
return new DashMediaSource.Factory(new DefaultDashChunkSource.Factory( return new DashMediaSource.Factory(
cacheDataSourceFactory), cacheDataSourceFactory); getDefaultDashChunkSourceFactory(cacheDataSourceFactory),
cacheDataSourceFactory
);
} }
public ProgressiveMediaSource.Factory getExtractorMediaSourceFactory() { public ProgressiveMediaSource.Factory getExtractorMediaSourceFactory() {
return new ProgressiveMediaSource.Factory(cacheDataSourceFactory) final ProgressiveMediaSource.Factory factory;
.setLoadErrorHandlingPolicy( if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
new DefaultLoadErrorHandlingPolicy(EXTRACTOR_MINIMUM_RETRY)); factory = new ProgressiveMediaSource.Factory(
} cacheDataSourceFactory,
MediaParserExtractorAdapter.FACTORY
);
} else {
factory = new ProgressiveMediaSource.Factory(cacheDataSourceFactory);
}
public ProgressiveMediaSource.Factory getExtractorMediaSourceFactory( return factory.setLoadErrorHandlingPolicy(
@NonNull final String key) { new DefaultLoadErrorHandlingPolicy(EXTRACTOR_MINIMUM_RETRY));
return getExtractorMediaSourceFactory().setCustomCacheKey(key);
} }
public SingleSampleMediaSource.Factory getSampleMediaSourceFactory() { public SingleSampleMediaSource.Factory getSampleMediaSourceFactory() {

View File

@ -1,5 +1,18 @@
package org.schabi.newpipe.player.helper; package org.schabi.newpipe.player.helper;
import static com.google.android.exoplayer2.Player.REPEAT_MODE_ALL;
import static com.google.android.exoplayer2.Player.REPEAT_MODE_OFF;
import static com.google.android.exoplayer2.Player.REPEAT_MODE_ONE;
import static org.schabi.newpipe.player.Player.IDLE_WINDOW_FLAGS;
import static org.schabi.newpipe.player.Player.PLAYER_TYPE;
import static org.schabi.newpipe.player.helper.PlayerHelper.AutoplayType.AUTOPLAY_TYPE_ALWAYS;
import static org.schabi.newpipe.player.helper.PlayerHelper.AutoplayType.AUTOPLAY_TYPE_NEVER;
import static org.schabi.newpipe.player.helper.PlayerHelper.AutoplayType.AUTOPLAY_TYPE_WIFI;
import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_BACKGROUND;
import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_NONE;
import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_POPUP;
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -21,11 +34,11 @@ import androidx.preference.PreferenceManager;
import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player.RepeatMode; import com.google.android.exoplayer2.Player.RepeatMode;
import com.google.android.exoplayer2.SeekParameters; import com.google.android.exoplayer2.SeekParameters;
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.ExoTrackSelection;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout.ResizeMode; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout.ResizeMode;
import com.google.android.exoplayer2.ui.CaptionStyleCompat;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import org.schabi.newpipe.R; import org.schabi.newpipe.R;
@ -57,19 +70,6 @@ import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import static com.google.android.exoplayer2.Player.REPEAT_MODE_ALL;
import static com.google.android.exoplayer2.Player.REPEAT_MODE_OFF;
import static com.google.android.exoplayer2.Player.REPEAT_MODE_ONE;
import static java.lang.annotation.RetentionPolicy.SOURCE;
import static org.schabi.newpipe.player.Player.IDLE_WINDOW_FLAGS;
import static org.schabi.newpipe.player.Player.PLAYER_TYPE;
import static org.schabi.newpipe.player.helper.PlayerHelper.AutoplayType.AUTOPLAY_TYPE_ALWAYS;
import static org.schabi.newpipe.player.helper.PlayerHelper.AutoplayType.AUTOPLAY_TYPE_NEVER;
import static org.schabi.newpipe.player.helper.PlayerHelper.AutoplayType.AUTOPLAY_TYPE_WIFI;
import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_BACKGROUND;
import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_NONE;
import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_POPUP;
public final class PlayerHelper { public final class PlayerHelper {
private static final StringBuilder STRING_BUILDER = new StringBuilder(); private static final StringBuilder STRING_BUILDER = new StringBuilder();
private static final Formatter STRING_FORMATTER private static final Formatter STRING_FORMATTER
@ -312,7 +312,7 @@ public final class PlayerHelper {
return 500; return 500;
} }
public static TrackSelection.Factory getQualitySelector() { public static ExoTrackSelection.Factory getQualitySelector() {
return new AdaptiveTrackSelection.Factory( return new AdaptiveTrackSelection.Factory(
1000, 1000,
AdaptiveTrackSelection.DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS, AdaptiveTrackSelection.DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS,

View File

@ -13,7 +13,7 @@ import com.google.android.exoplayer2.RendererCapabilities.Capabilities;
import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroup;
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.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
/** /**
@ -28,7 +28,7 @@ public class CustomTrackSelector extends DefaultTrackSelector {
private String preferredTextLanguage; private String preferredTextLanguage;
public CustomTrackSelector(final Context context, public CustomTrackSelector(final Context context,
final TrackSelection.Factory adaptiveTrackSelectionFactory) { final ExoTrackSelection.Factory adaptiveTrackSelectionFactory) {
super(context, adaptiveTrackSelectionFactory); super(context, adaptiveTrackSelectionFactory);
} }
@ -50,7 +50,7 @@ public class CustomTrackSelector extends DefaultTrackSelector {
@Override @Override
@Nullable @Nullable
protected Pair<TrackSelection.Definition, TextTrackScore> selectTextTrack( protected Pair<ExoTrackSelection.Definition, TextTrackScore> selectTextTrack(
final TrackGroupArray groups, final TrackGroupArray groups,
@NonNull final int[][] formatSupport, @NonNull final int[][] formatSupport,
@NonNull final Parameters params, @NonNull final Parameters params,
@ -86,7 +86,7 @@ public class CustomTrackSelector extends DefaultTrackSelector {
} }
} }
return selectedGroup == null ? null return selectedGroup == null ? null
: Pair.create(new TrackSelection.Definition(selectedGroup, selectedTrackIndex), : Pair.create(new ExoTrackSelection.Definition(selectedGroup, selectedTrackIndex),
Assertions.checkNotNull(selectedTrackScore)); Assertions.checkNotNull(selectedTrackScore));
} }
} }

View File

@ -9,6 +9,7 @@ import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MediaSourceFactory;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.StreamInfo;
@ -41,20 +42,28 @@ public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
@NonNull final String sourceUrl, @NonNull final String sourceUrl,
@C.ContentType final int type, @C.ContentType final int type,
@NonNull final MediaSourceTag metadata) { @NonNull final MediaSourceTag metadata) {
final Uri uri = Uri.parse(sourceUrl); final MediaSourceFactory factory;
switch (type) { switch (type) {
case C.TYPE_SS: case C.TYPE_SS:
return dataSource.getLiveSsMediaSourceFactory().setTag(metadata) factory = dataSource.getLiveSsMediaSourceFactory();
.createMediaSource(MediaItem.fromUri(uri)); break;
case C.TYPE_DASH: case C.TYPE_DASH:
return dataSource.getLiveDashMediaSourceFactory().setTag(metadata) factory = dataSource.getLiveDashMediaSourceFactory();
.createMediaSource(MediaItem.fromUri(uri)); break;
case C.TYPE_HLS: case C.TYPE_HLS:
return dataSource.getLiveHlsMediaSourceFactory().setTag(metadata) factory = dataSource.getLiveHlsMediaSourceFactory();
.createMediaSource(MediaItem.fromUri(uri)); break;
default: default:
throw new IllegalStateException("Unsupported type: " + type); throw new IllegalStateException("Unsupported type: " + type);
} }
return factory.createMediaSource(
new MediaItem.Builder()
.setTag(metadata)
.setUri(Uri.parse(sourceUrl))
.setLiveTargetOffsetMs(PlayerDataSource.LIVE_STREAM_EDGE_GAP_MILLIS)
.build()
);
} }
@NonNull @NonNull
@ -67,21 +76,30 @@ public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
@C.ContentType final int type = TextUtils.isEmpty(overrideExtension) @C.ContentType final int type = TextUtils.isEmpty(overrideExtension)
? Util.inferContentType(uri) : Util.inferContentType("." + overrideExtension); ? Util.inferContentType(uri) : Util.inferContentType("." + overrideExtension);
final MediaSourceFactory factory;
switch (type) { switch (type) {
case C.TYPE_SS: case C.TYPE_SS:
return dataSource.getLiveSsMediaSourceFactory().setTag(metadata) factory = dataSource.getLiveSsMediaSourceFactory();
.createMediaSource(MediaItem.fromUri(uri)); break;
case C.TYPE_DASH: case C.TYPE_DASH:
return dataSource.getDashMediaSourceFactory().setTag(metadata) factory = dataSource.getDashMediaSourceFactory();
.createMediaSource(MediaItem.fromUri(uri)); break;
case C.TYPE_HLS: case C.TYPE_HLS:
return dataSource.getHlsMediaSourceFactory().setTag(metadata) factory = dataSource.getHlsMediaSourceFactory();
.createMediaSource(MediaItem.fromUri(uri)); break;
case C.TYPE_OTHER: case C.TYPE_OTHER:
return dataSource.getExtractorMediaSourceFactory(cacheKey).setTag(metadata) factory = dataSource.getExtractorMediaSourceFactory();
.createMediaSource(MediaItem.fromUri(uri)); break;
default: default:
throw new IllegalStateException("Unsupported type: " + type); throw new IllegalStateException("Unsupported type: " + type);
} }
return factory.createMediaSource(
new MediaItem.Builder()
.setTag(metadata)
.setUri(uri)
.setCustomCacheKey(cacheKey)
.build()
);
} }
} }