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:
commit
dfba10f8ae
@ -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'
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 =
|
||||||
|
new HlsMediaSource.Factory(cachelessDataSourceFactory)
|
||||||
.setAllowChunklessPreparation(true)
|
.setAllowChunklessPreparation(true)
|
||||||
.setLoadErrorHandlingPolicy(
|
.setLoadErrorHandlingPolicy(
|
||||||
new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY));
|
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(
|
||||||
|
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() {
|
||||||
|
@ -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,
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user