mirror of
https://github.com/TeamNewPipe/NewPipe.git
synced 2024-11-25 12:32:31 +01:00
added: documentations to MediaItemTags and Player.
fixed: checkStyle failures.
This commit is contained in:
parent
4e459b3383
commit
69646e5b5d
@ -133,7 +133,6 @@ import com.google.android.exoplayer2.PlaybackException;
|
||||
import com.google.android.exoplayer2.PlaybackParameters;
|
||||
import com.google.android.exoplayer2.Player.PositionInfo;
|
||||
import com.google.android.exoplayer2.RenderersFactory;
|
||||
import com.google.android.exoplayer2.SeekParameters;
|
||||
import com.google.android.exoplayer2.Timeline;
|
||||
import com.google.android.exoplayer2.TracksInfo;
|
||||
import com.google.android.exoplayer2.source.MediaSource;
|
||||
@ -2487,6 +2486,7 @@ public final class Player implements
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
//region ExoPlayer listeners (that didn't fit in other categories)
|
||||
|
||||
@Override
|
||||
public void onEvents(@NonNull final com.google.android.exoplayer2.Player player,
|
||||
@NonNull final com.google.android.exoplayer2.Player.Events events) {
|
||||
Listener.super.onEvents(player, events);
|
||||
@ -2546,14 +2546,6 @@ public final class Player implements
|
||||
return;
|
||||
}
|
||||
|
||||
if (newPosition.contentPositionMs == 0 &&
|
||||
simpleExoPlayer.getTotalBufferedDuration() < 500L) {
|
||||
Log.d(TAG, "Playback - skipping to initial keyframe.");
|
||||
simpleExoPlayer.setSeekParameters(SeekParameters.CLOSEST_SYNC);
|
||||
simpleExoPlayer.seekTo(1L);
|
||||
simpleExoPlayer.setSeekParameters(PlayerHelper.getSeekParameters(context));
|
||||
}
|
||||
|
||||
// Refresh the playback if there is a transition to the next video
|
||||
final int newIndex = newPosition.mediaItemIndex;
|
||||
switch (discontinuityReason) {
|
||||
@ -2605,7 +2597,29 @@ public final class Player implements
|
||||
//region Errors
|
||||
/**
|
||||
* Process exceptions produced by {@link com.google.android.exoplayer2.ExoPlayer ExoPlayer}.
|
||||
*
|
||||
* <p>There are multiple types of errors:</p>
|
||||
* <ul>
|
||||
* <li>{@link PlaybackException#ERROR_CODE_BEHIND_LIVE_WINDOW BEHIND_LIVE_WINDOW}:
|
||||
* If the playback on livestreams are lagged too far behind the current playable
|
||||
* window. Then we seek to the latest timestamp and restart the playback.
|
||||
* </li>
|
||||
* <li>From {@link PlaybackException#ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE BAD_IO} to
|
||||
* {@link PlaybackException#ERROR_CODE_PARSING_MANIFEST_UNSUPPORTED UNSUPPORTED_FORMATS}:
|
||||
* If the stream source is validated by the extractor but not recognized by the player,
|
||||
* then we can try to recover playback by signal an error on the {@link PlayQueue}.</li>
|
||||
* <li>For {@link PlaybackException#ERROR_CODE_TIMEOUT PLAYER_TIMEOUT},
|
||||
* {@link PlaybackException#ERROR_CODE_IO_UNSPECIFIED MEDIA_SOURCE_RESOLVER_TIMEOUT} and
|
||||
* {@link PlaybackException#ERROR_CODE_IO_NETWORK_CONNECTION_FAILED NO_NETWORK}:
|
||||
* We can keep set the recovery record and keep to player at the current state until
|
||||
* it is ready to play by restarting the {@link MediaSourceManager}.</li>
|
||||
* <li>On any ExoPlayer specific issue internal to its device interaction, such as
|
||||
* {@link PlaybackException#ERROR_CODE_DECODER_INIT_FAILED DECODER_ERROR}:
|
||||
* We terminate the playback.</li>
|
||||
* <li>For any other unspecified issue internal: We set a recovery and try to restart
|
||||
* the playback.</li>
|
||||
* In the case of decoder/renderer or unspecified errors, the player will create a
|
||||
* notification so the users are aware.
|
||||
* </ul>
|
||||
* @see com.google.android.exoplayer2.Player.Listener#onPlayerError(PlaybackException)
|
||||
* */
|
||||
@SuppressLint("SwitchIntDef")
|
||||
@ -2648,6 +2662,9 @@ public final class Player implements
|
||||
case ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT:
|
||||
// Don't create notification on timeout/networking errors:
|
||||
isCatchableException = true;
|
||||
setRecovery();
|
||||
reloadPlayQueueManager();
|
||||
break;
|
||||
case ERROR_CODE_UNSPECIFIED:
|
||||
// Reload playback on unexpected errors:
|
||||
setRecovery();
|
||||
@ -2749,7 +2766,6 @@ public final class Player implements
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean onPlaybackInitial = currentItem == null;
|
||||
final boolean hasPlayQueueItemChanged = currentItem != item;
|
||||
|
||||
final int currentPlayQueueIndex = playQueue.indexOf(item);
|
||||
@ -2953,10 +2969,8 @@ public final class Player implements
|
||||
//region StreamInfo history: views and progress
|
||||
|
||||
private void registerStreamViewed() {
|
||||
getCurrentStreamInfo().ifPresent(info -> {
|
||||
databaseUpdateDisposable
|
||||
.add(recordManager.onViewed(info).onErrorComplete().subscribe());
|
||||
});
|
||||
getCurrentStreamInfo().ifPresent(info -> databaseUpdateDisposable
|
||||
.add(recordManager.onViewed(info).onErrorComplete().subscribe()));
|
||||
}
|
||||
|
||||
private void saveStreamProgressState(final long progressMillis) {
|
||||
@ -3134,7 +3148,7 @@ public final class Player implements
|
||||
return;
|
||||
}
|
||||
|
||||
if (playQueue.getIndex() == index && simpleExoPlayer.getCurrentWindowIndex() == index) {
|
||||
if (playQueue.getIndex() == index && simpleExoPlayer.getCurrentMediaItemIndex() == index) {
|
||||
seekToDefault();
|
||||
} else {
|
||||
saveStreamProgressState();
|
||||
@ -3880,9 +3894,10 @@ public final class Player implements
|
||||
}
|
||||
|
||||
private void onOpenInBrowserClicked() {
|
||||
getCurrentStreamInfo().map(Info::getOriginalUrl).ifPresent(originalUrl -> {
|
||||
ShareUtils.openUrlInBrowser(Objects.requireNonNull(getParentActivity()), originalUrl);
|
||||
});
|
||||
getCurrentStreamInfo()
|
||||
.map(Info::getOriginalUrl)
|
||||
.ifPresent(originalUrl -> ShareUtils.openUrlInBrowser(
|
||||
Objects.requireNonNull(getParentActivity()), originalUrl));
|
||||
}
|
||||
//endregion
|
||||
|
||||
|
@ -10,6 +10,16 @@ import java.util.Optional;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* This {@link MediaItemTag} object is designed to contain metadata for a stream
|
||||
* that has failed to load. It supplies metadata from an underlying
|
||||
* {@link PlayQueueItem}, which is used by the internal players to resolve actual
|
||||
* playback info.
|
||||
*
|
||||
* This {@link MediaItemTag} does not contain any {@link StreamInfo} that can be
|
||||
* used to start playback and can be detected by checking {@link ExceptionTag#getErrors()}
|
||||
* when in generic form.
|
||||
**/
|
||||
public final class ExceptionTag implements MediaItemTag {
|
||||
@NonNull
|
||||
private final PlayQueueItem item;
|
||||
|
@ -4,6 +4,7 @@ import android.net.Uri;
|
||||
|
||||
import com.google.android.exoplayer2.MediaItem;
|
||||
import com.google.android.exoplayer2.MediaMetadata;
|
||||
import com.google.android.exoplayer2.Player;
|
||||
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||
@ -16,6 +17,13 @@ import java.util.UUID;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Metadata container and accessor used by player internals.
|
||||
*
|
||||
* This interface ensures consistency of fetching metadata on each stream,
|
||||
* which is encapsulated in a {@link MediaItem} and delivered via ExoPlayer's
|
||||
* {@link Player.Listener} on event triggers to the downstream users.
|
||||
**/
|
||||
public interface MediaItemTag {
|
||||
|
||||
List<Throwable> getErrors();
|
||||
|
@ -2,6 +2,7 @@ package org.schabi.newpipe.player.mediaitem;
|
||||
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||
import org.schabi.newpipe.util.Constants;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@ -10,6 +11,12 @@ import java.util.Optional;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* This is a Placeholding {@link MediaItemTag}, designed as a dummy metadata object for
|
||||
* any stream that has not been resolved.
|
||||
*
|
||||
* This object cannot be instantiated and does not hold real metadata of any form.
|
||||
* */
|
||||
public final class PlaceholderTag implements MediaItemTag {
|
||||
public static final PlaceholderTag EMPTY = new PlaceholderTag(null);
|
||||
private static final String UNKNOWN_VALUE_INTERNAL = "Placeholder";
|
||||
@ -29,7 +36,7 @@ public final class PlaceholderTag implements MediaItemTag {
|
||||
|
||||
@Override
|
||||
public int getServiceId() {
|
||||
return -1;
|
||||
return Constants.NO_SERVICE_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -44,7 +51,7 @@ public final class PlaceholderTag implements MediaItemTag {
|
||||
|
||||
@Override
|
||||
public long getDurationSeconds() {
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,5 +1,7 @@
|
||||
package org.schabi.newpipe.player.mediaitem;
|
||||
|
||||
import com.google.android.exoplayer2.MediaItem;
|
||||
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||
import org.schabi.newpipe.extractor.stream.VideoStream;
|
||||
@ -11,6 +13,12 @@ import java.util.Optional;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* This {@link MediaItemTag} object contains metadata for a resolved stream
|
||||
* that is ready for playback. This object guarantees the {@link StreamInfo}
|
||||
* is available and may provide the {@link Quality} of video stream used in
|
||||
* the {@link MediaItem}.
|
||||
**/
|
||||
public final class StreamInfoTag implements MediaItemTag {
|
||||
@NonNull
|
||||
private final StreamInfo streamInfo;
|
||||
|
@ -23,7 +23,15 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class FailedMediaSource extends CompositeMediaSource<Void> implements ManagedMediaSource {
|
||||
private static final long SILENCE_DURATION_US = TimeUnit.SECONDS.toMicros(2);
|
||||
/**
|
||||
* Play 2 seconds of silenced audio when a stream fails to resolve due to a known issue,
|
||||
* such as {@link org.schabi.newpipe.extractor.exceptions.ExtractionException}.
|
||||
*
|
||||
* This silence duration allows user to react and have time to jump to a previous stream,
|
||||
* while still provide a smooth playback experience. A duration lower than 1 second is
|
||||
* not recommended, it may cause ExoPlayer to buffer for a while.
|
||||
* */
|
||||
public static final long SILENCE_DURATION_US = TimeUnit.SECONDS.toMicros(2);
|
||||
|
||||
private final String TAG = "FailedMediaSource@" + Integer.toHexString(hashCode());
|
||||
private final PlayQueueItem playQueueItem;
|
||||
@ -32,7 +40,7 @@ public class FailedMediaSource extends CompositeMediaSource<Void> implements Man
|
||||
private final MediaSource source;
|
||||
private final MediaItem mediaItem;
|
||||
/**
|
||||
* Permanently fail the play queue item associated with this source, with no hope of retrying.
|
||||
* Fail the play queue item associated with this source, with potential future retries.
|
||||
*
|
||||
* The error will be propagated if the cause for load exception is unspecified.
|
||||
* This means the error might be caused by reasons outside of extraction (e.g. no network).
|
||||
|
Loading…
Reference in New Issue
Block a user