Merge branch 'dev' into daynight

This commit is contained in:
krlvm 2021-04-03 00:08:26 +03:00 committed by GitHub
commit ef0999b9c3
105 changed files with 1017 additions and 942 deletions

View file

@ -76,6 +76,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
import com.google.android.exoplayer2.ui.SubtitleView;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.VideoListener;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.nostra13.universalimageloader.core.ImageLoader;
@ -493,10 +494,12 @@ public final class Player implements
// Setup subtitle view
simpleExoPlayer.addTextOutput(binding.subtitleView);
// Setup audio session with onboard equalizer
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
trackSelector.setParameters(trackSelector.buildUponParameters()
.setTunnelingAudioSessionId(C.generateAudioSessionIdV21(context)));
// enable media tunneling
if (DeviceUtils.shouldSupportMediaTunneling()) {
trackSelector.setParameters(
trackSelector.buildUponParameters().setTunnelingEnabled(true));
} else if (DEBUG) {
Log.d(TAG, "[" + Util.DEVICE_DEBUG_INFO + "] does not support media tunneling");
}
}
@ -629,10 +632,10 @@ public final class Player implements
&& newQueue.getItem().getUrl().equals(playQueue.getItem().getUrl())
&& newQueue.getItem().getRecoveryPosition() != PlayQueueItem.RECOVERY_UNSET) {
// Player can have state = IDLE when playback is stopped or failed
// and we should retry() in this case
// and we should retry in this case
if (simpleExoPlayer.getPlaybackState()
== com.google.android.exoplayer2.Player.STATE_IDLE) {
simpleExoPlayer.retry();
simpleExoPlayer.prepare();
}
simpleExoPlayer.seekTo(playQueue.getIndex(), newQueue.getItem().getRecoveryPosition());
simpleExoPlayer.setPlayWhenReady(playWhenReady);
@ -643,10 +646,10 @@ public final class Player implements
&& !playQueue.isDisposed()) {
// Do not re-init the same PlayQueue. Save time
// Player can have state = IDLE when playback is stopped or failed
// and we should retry() in this case
// and we should retry in this case
if (simpleExoPlayer.getPlaybackState()
== com.google.android.exoplayer2.Player.STATE_IDLE) {
simpleExoPlayer.retry();
simpleExoPlayer.prepare();
}
simpleExoPlayer.setPlayWhenReady(playWhenReady);
@ -711,11 +714,7 @@ public final class Player implements
// Android TV: without it focus will frame the whole player
binding.playPauseButton.requestFocus();
if (simpleExoPlayer.getPlayWhenReady()) {
play();
} else {
pause();
}
playPause();
}
NavigationHelper.sendPlayerStartedEvent(context);
}
@ -1658,7 +1657,7 @@ public final class Player implements
saveWasPlaying();
if (isPlaying()) {
simpleExoPlayer.setPlayWhenReady(false);
simpleExoPlayer.pause();
}
showControls(0);
@ -1674,7 +1673,7 @@ public final class Player implements
seekTo(seekBar.getProgress());
if (wasPlaying || simpleExoPlayer.getDuration() == seekBar.getProgress()) {
simpleExoPlayer.setPlayWhenReady(true);
simpleExoPlayer.play();
}
binding.playbackCurrentTime.setText(getTimeString(seekBar.getProgress()));
@ -1692,7 +1691,7 @@ public final class Player implements
}
public void saveWasPlaying() {
this.wasPlaying = simpleExoPlayer.getPlayWhenReady();
this.wasPlaying = getPlayWhenReady();
}
//endregion
@ -1917,7 +1916,7 @@ public final class Player implements
}
@Override // exoplayer listener
public void onLoadingChanged(final boolean isLoading) {
public void onIsLoadingChanged(final boolean isLoading) {
if (DEBUG) {
Log.d(TAG, "ExoPlayer - onLoadingChanged() called with: "
+ "isLoading = [" + isLoading + "]");
@ -1961,7 +1960,8 @@ public final class Player implements
if (currentState == STATE_BLOCKED) {
changeState(STATE_BUFFERING);
}
simpleExoPlayer.prepare(mediaSource);
simpleExoPlayer.setMediaSource(mediaSource);
simpleExoPlayer.prepare();
}
public void changeState(final int state) {
@ -2360,6 +2360,12 @@ public final class Player implements
break;
}
case DISCONTINUITY_REASON_SEEK:
if (DEBUG) {
Log.d(TAG, "ExoPlayer - onSeekProcessed() called");
}
if (isPrepared) {
saveStreamProgressState();
}
case DISCONTINUITY_REASON_SEEK_ADJUSTMENT:
case DISCONTINUITY_REASON_INTERNAL:
if (playQueue.getIndex() != newWindowIndex) {
@ -2424,10 +2430,8 @@ public final class Player implements
setRecovery();
reloadPlayQueueManager();
break;
case ExoPlaybackException.TYPE_OUT_OF_MEMORY:
case ExoPlaybackException.TYPE_REMOTE:
case ExoPlaybackException.TYPE_RENDERER:
case ExoPlaybackException.TYPE_TIMEOUT:
default:
showUnrecoverableError(error);
onPlaybackShutdown();
@ -2632,16 +2636,6 @@ public final class Player implements
simpleExoPlayer.seekToDefaultPosition();
}
}
@Override // exoplayer override
public void onSeekProcessed() {
if (DEBUG) {
Log.d(TAG, "ExoPlayer - onSeekProcessed() called");
}
if (isPrepared) {
saveStreamProgressState();
}
}
//endregion
@ -2669,7 +2663,7 @@ public final class Player implements
}
}
simpleExoPlayer.setPlayWhenReady(true);
simpleExoPlayer.play();
saveStreamProgressState();
}
@ -2682,7 +2676,7 @@ public final class Player implements
}
audioReactor.abandonAudioFocus();
simpleExoPlayer.setPlayWhenReady(false);
simpleExoPlayer.pause();
saveStreamProgressState();
}
@ -2691,7 +2685,7 @@ public final class Player implements
Log.d(TAG, "onPlayPause() called");
}
if (isPlaying()) {
if (getPlayWhenReady()) {
pause();
} else {
play();
@ -4017,6 +4011,10 @@ public final class Player implements
return !exoPlayerIsNull() && simpleExoPlayer.isPlaying();
}
public boolean getPlayWhenReady() {
return !exoPlayerIsNull() && simpleExoPlayer.getPlayWhenReady();
}
private boolean isLoading() {
return !exoPlayerIsNull() && simpleExoPlayer.isLoading();
}

View file

@ -229,8 +229,10 @@ abstract class BasePlayerGestureListener(
// because the soft input is visible (the draggable area is currently resized).
player.updateScreenSize()
player.checkPopupPositionBounds()
initialPopupX = player.popupLayoutParams!!.x
initialPopupY = player.popupLayoutParams!!.y
player.popupLayoutParams?.let {
initialPopupX = it.x
initialPopupY = it.y
}
return super.onDown(e)
}
@ -466,7 +468,7 @@ abstract class BasePlayerGestureListener(
// ///////////////////////////////////////////////////////////////////
private fun getDisplayPortion(e: MotionEvent): DisplayPortion {
return if (player.playerType == MainPlayer.PlayerType.POPUP) {
return if (player.playerType == MainPlayer.PlayerType.POPUP && player.popupLayoutParams != null) {
when {
e.x < player.popupLayoutParams!!.width / 3.0 -> DisplayPortion.LEFT
e.x > player.popupLayoutParams!!.width * 2.0 / 3.0 -> DisplayPortion.RIGHT

View file

@ -26,7 +26,7 @@ public class CustomBottomSheetBehavior extends BottomSheetBehavior<FrameLayout>
Rect globalRect = new Rect();
private boolean skippingInterception = false;
private final List<Integer> skipInterceptionOfElements = Arrays.asList(
R.id.detail_content_root_layout, R.id.relatedStreamsLayout,
R.id.detail_content_root_layout, R.id.relatedItemsLayout,
R.id.itemsListPanel, R.id.view_pager, R.id.tab_layout, R.id.bottomControls,
R.id.playPauseButton, R.id.playPreviousButton, R.id.playNextButton);

View file

@ -103,13 +103,13 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, An
animateAudio(DUCK_AUDIO_TO, 1.0f);
if (PlayerHelper.isResumeAfterAudioFocusGain(context)) {
player.setPlayWhenReady(true);
player.play();
}
}
private void onAudioFocusLoss() {
Log.d(TAG, "onAudioFocusLoss() called");
player.setPlayWhenReady(false);
player.pause();
}
private void onAudioFocusLossCanDuck() {
@ -148,7 +148,7 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, An
//////////////////////////////////////////////////////////////////////////*/
@Override
public void onAudioSessionId(final EventTime eventTime, final int audioSessionId) {
public void onAudioSessionIdChanged(final EventTime eventTime, final int audioSessionId) {
if (!PlayerHelper.isUsingDSP()) {
return;
}

View file

@ -4,7 +4,7 @@ import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.LoadControl;
import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.upstream.Allocator;
public class LoadController implements LoadControl {
@ -33,7 +33,7 @@ public class LoadController implements LoadControl {
final DefaultLoadControl.Builder builder = new DefaultLoadControl.Builder();
builder.setBufferDurationsMs(minimumPlaybackBufferMs, optimalPlaybackBufferMs,
initialPlaybackBufferMs, initialPlaybackBufferMs);
internalLoadControl = builder.createDefaultLoadControl();
internalLoadControl = builder.build();
}
/*//////////////////////////////////////////////////////////////////////////
@ -47,9 +47,9 @@ public class LoadController implements LoadControl {
}
@Override
public void onTracksSelected(final Renderer[] renderers, final TrackGroupArray trackGroupArray,
final TrackSelectionArray trackSelectionArray) {
internalLoadControl.onTracksSelected(renderers, trackGroupArray, trackSelectionArray);
public void onTracksSelected(final Renderer[] renderers, final TrackGroupArray trackGroups,
final ExoTrackSelection[] trackSelections) {
internalLoadControl.onTracksSelected(renderers, trackGroups, trackSelections);
}
@Override
@ -92,11 +92,12 @@ public class LoadController implements LoadControl {
@Override
public boolean shouldStartPlayback(final long bufferedDurationUs, final float playbackSpeed,
final boolean rebuffering) {
final boolean rebuffering, final long targetLiveOffsetUs) {
final boolean isInitialPlaybackBufferFilled
= bufferedDurationUs >= this.initialPlaybackBufferUs * playbackSpeed;
final boolean isInternalStartingPlayback = internalLoadControl
.shouldStartPlayback(bufferedDurationUs, playbackSpeed, rebuffering);
.shouldStartPlayback(bufferedDurationUs, playbackSpeed, rebuffering,
targetLiveOffsetUs);
return isInitialPlaybackBufferFilled || isInternalStartingPlayback;
}

View file

@ -36,8 +36,6 @@ public class MediaSessionManager {
@NonNull final Player player,
@NonNull final MediaSessionCallback callback) {
mediaSession = new MediaSessionCompat(context, TAG);
mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS
| MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
mediaSession.setActive(true);
mediaSession.setPlaybackState(new PlaybackStateCompat.Builder()

View file

@ -23,7 +23,7 @@ import com.google.android.exoplayer2.Player.RepeatMode;
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.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout.ResizeMode;
import com.google.android.exoplayer2.util.MimeTypes;
@ -180,10 +180,10 @@ public final class PlayerHelper {
* if a candidate next video's url already exists in the existing items.
* </p>
* <p>
* The first item in {@link StreamInfo#getRelatedStreams()} is checked first.
* The first item in {@link StreamInfo#getRelatedItems()} is checked first.
* If it is non-null and is not part of the existing items, it will be used as the next stream.
* Otherwise, a random item with non-repeating url will be selected
* from the {@link StreamInfo#getRelatedStreams()}.
* Otherwise, a random stream with non-repeating url will be selected
* from the {@link StreamInfo#getRelatedItems()}. Non-stream items are ignored.
* </p>
*
* @param info currently playing stream
@ -198,7 +198,7 @@ public final class PlayerHelper {
urls.add(item.getUrl());
}
final List<InfoItem> relatedItems = info.getRelatedStreams();
final List<InfoItem> relatedItems = info.getRelatedItems();
if (Utils.isNullOrEmpty(relatedItems)) {
return null;
}
@ -323,7 +323,7 @@ public final class PlayerHelper {
return 60000;
}
public static TrackSelection.Factory getQualitySelector() {
public static ExoTrackSelection.Factory getQualitySelector() {
return new AdaptiveTrackSelection.Factory(
1000,
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.TrackGroupArray;
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;
/**
@ -28,7 +28,7 @@ public class CustomTrackSelector extends DefaultTrackSelector {
private String preferredTextLanguage;
public CustomTrackSelector(final Context context,
final TrackSelection.Factory adaptiveTrackSelectionFactory) {
final ExoTrackSelection.Factory adaptiveTrackSelectionFactory) {
super(context, adaptiveTrackSelectionFactory);
}
@ -50,7 +50,7 @@ public class CustomTrackSelector extends DefaultTrackSelector {
@Override
@Nullable
protected Pair<TrackSelection.Definition, TextTrackScore> selectTextTrack(
protected Pair<ExoTrackSelection.Definition, TextTrackScore> selectTextTrack(
final TrackGroupArray groups,
@NonNull final int[][] formatSupport,
@NonNull final Parameters params,
@ -86,7 +86,7 @@ public class CustomTrackSelector extends DefaultTrackSelector {
}
}
return selectedGroup == null ? null
: Pair.create(new TrackSelection.Definition(selectedGroup, selectedTrackIndex),
: Pair.create(new ExoTrackSelection.Definition(selectedGroup, selectedTrackIndex),
Assertions.checkNotNull(selectedTrackScore));
}
}

View file

@ -7,6 +7,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.util.Util;
@ -43,13 +44,13 @@ public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
switch (type) {
case C.TYPE_SS:
return dataSource.getLiveSsMediaSourceFactory().setTag(metadata)
.createMediaSource(uri);
.createMediaSource(MediaItem.fromUri(uri));
case C.TYPE_DASH:
return dataSource.getLiveDashMediaSourceFactory().setTag(metadata)
.createMediaSource(uri);
.createMediaSource(MediaItem.fromUri(uri));
case C.TYPE_HLS:
return dataSource.getLiveHlsMediaSourceFactory().setTag(metadata)
.createMediaSource(uri);
.createMediaSource(MediaItem.fromUri(uri));
default:
throw new IllegalStateException("Unsupported type: " + type);
}
@ -68,16 +69,16 @@ public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
switch (type) {
case C.TYPE_SS:
return dataSource.getLiveSsMediaSourceFactory().setTag(metadata)
.createMediaSource(uri);
.createMediaSource(MediaItem.fromUri(uri));
case C.TYPE_DASH:
return dataSource.getDashMediaSourceFactory().setTag(metadata)
.createMediaSource(uri);
.createMediaSource(MediaItem.fromUri(uri));
case C.TYPE_HLS:
return dataSource.getHlsMediaSourceFactory().setTag(metadata)
.createMediaSource(uri);
.createMediaSource(MediaItem.fromUri(uri));
case C.TYPE_OTHER:
return dataSource.getExtractorMediaSourceFactory(cacheKey).setTag(metadata)
.createMediaSource(uri);
.createMediaSource(MediaItem.fromUri(uri));
default:
throw new IllegalStateException("Unsupported type: " + type);
}

View file

@ -6,7 +6,7 @@ import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MergingMediaSource;
@ -22,7 +22,6 @@ import org.schabi.newpipe.util.ListHelper;
import java.util.ArrayList;
import java.util.List;
import static com.google.android.exoplayer2.C.SELECTION_FLAG_AUTOSELECT;
import static com.google.android.exoplayer2.C.TIME_UNSET;
public class VideoPlaybackResolver implements PlaybackResolver {
@ -101,12 +100,12 @@ public class VideoPlaybackResolver implements PlaybackResolver {
if (mimeType == null) {
continue;
}
final Format textFormat = Format.createTextSampleFormat(null, mimeType,
SELECTION_FLAG_AUTOSELECT,
PlayerHelper.captionLanguageOf(context, subtitle));
final MediaSource textSource = dataSource.getSampleMediaSourceFactory()
.createMediaSource(Uri.parse(subtitle.getUrl()), textFormat, TIME_UNSET);
.createMediaSource(
new MediaItem.Subtitle(Uri.parse(subtitle.getUrl()),
mimeType,
PlayerHelper.captionLanguageOf(context, subtitle)),
TIME_UNSET);
mediaSources.add(textSource);
}
}