Skip to content

Commit 69646e5

Browse files
committed
added: documentations to MediaItemTags and Player.
fixed: checkStyle failures.
1 parent 4e459b3 commit 69646e5

6 files changed

Lines changed: 79 additions & 23 deletions

File tree

app/src/main/java/org/schabi/newpipe/player/Player.java

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,6 @@
133133
import com.google.android.exoplayer2.PlaybackParameters;
134134
import com.google.android.exoplayer2.Player.PositionInfo;
135135
import com.google.android.exoplayer2.RenderersFactory;
136-
import com.google.android.exoplayer2.SeekParameters;
137136
import com.google.android.exoplayer2.Timeline;
138137
import com.google.android.exoplayer2.TracksInfo;
139138
import com.google.android.exoplayer2.source.MediaSource;
@@ -2487,6 +2486,7 @@ private void setMuteButton(@NonNull final ImageButton button, final boolean isMu
24872486
//////////////////////////////////////////////////////////////////////////*/
24882487
//region ExoPlayer listeners (that didn't fit in other categories)
24892488

2489+
@Override
24902490
public void onEvents(@NonNull final com.google.android.exoplayer2.Player player,
24912491
@NonNull final com.google.android.exoplayer2.Player.Events events) {
24922492
Listener.super.onEvents(player, events);
@@ -2546,14 +2546,6 @@ public void onPositionDiscontinuity(@NonNull final PositionInfo oldPosition,
25462546
return;
25472547
}
25482548

2549-
if (newPosition.contentPositionMs == 0 &&
2550-
simpleExoPlayer.getTotalBufferedDuration() < 500L) {
2551-
Log.d(TAG, "Playback - skipping to initial keyframe.");
2552-
simpleExoPlayer.setSeekParameters(SeekParameters.CLOSEST_SYNC);
2553-
simpleExoPlayer.seekTo(1L);
2554-
simpleExoPlayer.setSeekParameters(PlayerHelper.getSeekParameters(context));
2555-
}
2556-
25572549
// Refresh the playback if there is a transition to the next video
25582550
final int newIndex = newPosition.mediaItemIndex;
25592551
switch (discontinuityReason) {
@@ -2605,7 +2597,29 @@ public void onCues(@NonNull final List<Cue> cues) {
26052597
//region Errors
26062598
/**
26072599
* Process exceptions produced by {@link com.google.android.exoplayer2.ExoPlayer ExoPlayer}.
2608-
*
2600+
* <p>There are multiple types of errors:</p>
2601+
* <ul>
2602+
* <li>{@link PlaybackException#ERROR_CODE_BEHIND_LIVE_WINDOW BEHIND_LIVE_WINDOW}:
2603+
* If the playback on livestreams are lagged too far behind the current playable
2604+
* window. Then we seek to the latest timestamp and restart the playback.
2605+
* </li>
2606+
* <li>From {@link PlaybackException#ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE BAD_IO} to
2607+
* {@link PlaybackException#ERROR_CODE_PARSING_MANIFEST_UNSUPPORTED UNSUPPORTED_FORMATS}:
2608+
* If the stream source is validated by the extractor but not recognized by the player,
2609+
* then we can try to recover playback by signal an error on the {@link PlayQueue}.</li>
2610+
* <li>For {@link PlaybackException#ERROR_CODE_TIMEOUT PLAYER_TIMEOUT},
2611+
* {@link PlaybackException#ERROR_CODE_IO_UNSPECIFIED MEDIA_SOURCE_RESOLVER_TIMEOUT} and
2612+
* {@link PlaybackException#ERROR_CODE_IO_NETWORK_CONNECTION_FAILED NO_NETWORK}:
2613+
* We can keep set the recovery record and keep to player at the current state until
2614+
* it is ready to play by restarting the {@link MediaSourceManager}.</li>
2615+
* <li>On any ExoPlayer specific issue internal to its device interaction, such as
2616+
* {@link PlaybackException#ERROR_CODE_DECODER_INIT_FAILED DECODER_ERROR}:
2617+
* We terminate the playback.</li>
2618+
* <li>For any other unspecified issue internal: We set a recovery and try to restart
2619+
* the playback.</li>
2620+
* In the case of decoder/renderer or unspecified errors, the player will create a
2621+
* notification so the users are aware.
2622+
* </ul>
26092623
* @see com.google.android.exoplayer2.Player.Listener#onPlayerError(PlaybackException)
26102624
* */
26112625
@SuppressLint("SwitchIntDef")
@@ -2648,6 +2662,9 @@ public void onPlayerError(@NonNull final PlaybackException error) {
26482662
case ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT:
26492663
// Don't create notification on timeout/networking errors:
26502664
isCatchableException = true;
2665+
setRecovery();
2666+
reloadPlayQueueManager();
2667+
break;
26512668
case ERROR_CODE_UNSPECIFIED:
26522669
// Reload playback on unexpected errors:
26532670
setRecovery();
@@ -2749,7 +2766,6 @@ public void onPlaybackSynchronize(@NonNull final PlayQueueItem item, final boole
27492766
return;
27502767
}
27512768

2752-
final boolean onPlaybackInitial = currentItem == null;
27532769
final boolean hasPlayQueueItemChanged = currentItem != item;
27542770

27552771
final int currentPlayQueueIndex = playQueue.indexOf(item);
@@ -2953,10 +2969,8 @@ public void fastRewind() {
29532969
//region StreamInfo history: views and progress
29542970

29552971
private void registerStreamViewed() {
2956-
getCurrentStreamInfo().ifPresent(info -> {
2957-
databaseUpdateDisposable
2958-
.add(recordManager.onViewed(info).onErrorComplete().subscribe());
2959-
});
2972+
getCurrentStreamInfo().ifPresent(info -> databaseUpdateDisposable
2973+
.add(recordManager.onViewed(info).onErrorComplete().subscribe()));
29602974
}
29612975

29622976
private void saveStreamProgressState(final long progressMillis) {
@@ -3134,7 +3148,7 @@ public void selectQueueItem(final PlayQueueItem item) {
31343148
return;
31353149
}
31363150

3137-
if (playQueue.getIndex() == index && simpleExoPlayer.getCurrentWindowIndex() == index) {
3151+
if (playQueue.getIndex() == index && simpleExoPlayer.getCurrentMediaItemIndex() == index) {
31383152
seekToDefault();
31393153
} else {
31403154
saveStreamProgressState();
@@ -3880,9 +3894,10 @@ private void onPlayWithKodiClicked() {
38803894
}
38813895

38823896
private void onOpenInBrowserClicked() {
3883-
getCurrentStreamInfo().map(Info::getOriginalUrl).ifPresent(originalUrl -> {
3884-
ShareUtils.openUrlInBrowser(Objects.requireNonNull(getParentActivity()), originalUrl);
3885-
});
3897+
getCurrentStreamInfo()
3898+
.map(Info::getOriginalUrl)
3899+
.ifPresent(originalUrl -> ShareUtils.openUrlInBrowser(
3900+
Objects.requireNonNull(getParentActivity()), originalUrl));
38863901
}
38873902
//endregion
38883903

app/src/main/java/org/schabi/newpipe/player/mediaitem/ExceptionTag.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,16 @@
1010
import androidx.annotation.NonNull;
1111
import androidx.annotation.Nullable;
1212

13+
/**
14+
* This {@link MediaItemTag} object is designed to contain metadata for a stream
15+
* that has failed to load. It supplies metadata from an underlying
16+
* {@link PlayQueueItem}, which is used by the internal players to resolve actual
17+
* playback info.
18+
*
19+
* This {@link MediaItemTag} does not contain any {@link StreamInfo} that can be
20+
* used to start playback and can be detected by checking {@link ExceptionTag#getErrors()}
21+
* when in generic form.
22+
**/
1323
public final class ExceptionTag implements MediaItemTag {
1424
@NonNull
1525
private final PlayQueueItem item;

app/src/main/java/org/schabi/newpipe/player/mediaitem/MediaItemTag.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import com.google.android.exoplayer2.MediaItem;
66
import com.google.android.exoplayer2.MediaMetadata;
7+
import com.google.android.exoplayer2.Player;
78

89
import org.schabi.newpipe.extractor.stream.StreamInfo;
910
import org.schabi.newpipe.extractor.stream.StreamType;
@@ -16,6 +17,13 @@
1617
import androidx.annotation.NonNull;
1718
import androidx.annotation.Nullable;
1819

20+
/**
21+
* Metadata container and accessor used by player internals.
22+
*
23+
* This interface ensures consistency of fetching metadata on each stream,
24+
* which is encapsulated in a {@link MediaItem} and delivered via ExoPlayer's
25+
* {@link Player.Listener} on event triggers to the downstream users.
26+
**/
1927
public interface MediaItemTag {
2028

2129
List<Throwable> getErrors();

app/src/main/java/org/schabi/newpipe/player/mediaitem/PlaceholderTag.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import org.schabi.newpipe.extractor.stream.StreamInfo;
44
import org.schabi.newpipe.extractor.stream.StreamType;
5+
import org.schabi.newpipe.util.Constants;
56

67
import java.util.Collections;
78
import java.util.List;
@@ -10,6 +11,12 @@
1011
import androidx.annotation.NonNull;
1112
import androidx.annotation.Nullable;
1213

14+
/**
15+
* This is a Placeholding {@link MediaItemTag}, designed as a dummy metadata object for
16+
* any stream that has not been resolved.
17+
*
18+
* This object cannot be instantiated and does not hold real metadata of any form.
19+
* */
1320
public final class PlaceholderTag implements MediaItemTag {
1421
public static final PlaceholderTag EMPTY = new PlaceholderTag(null);
1522
private static final String UNKNOWN_VALUE_INTERNAL = "Placeholder";
@@ -29,7 +36,7 @@ public List<Throwable> getErrors() {
2936

3037
@Override
3138
public int getServiceId() {
32-
return -1;
39+
return Constants.NO_SERVICE_ID;
3340
}
3441

3542
@Override
@@ -44,7 +51,7 @@ public String getUploaderName() {
4451

4552
@Override
4653
public long getDurationSeconds() {
47-
return -1;
54+
return 0;
4855
}
4956

5057
@Override

app/src/main/java/org/schabi/newpipe/player/mediaitem/StreamInfoTag.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.schabi.newpipe.player.mediaitem;
22

3+
import com.google.android.exoplayer2.MediaItem;
4+
35
import org.schabi.newpipe.extractor.stream.StreamInfo;
46
import org.schabi.newpipe.extractor.stream.StreamType;
57
import org.schabi.newpipe.extractor.stream.VideoStream;
@@ -11,6 +13,12 @@
1113
import androidx.annotation.NonNull;
1214
import androidx.annotation.Nullable;
1315

16+
/**
17+
* This {@link MediaItemTag} object contains metadata for a resolved stream
18+
* that is ready for playback. This object guarantees the {@link StreamInfo}
19+
* is available and may provide the {@link Quality} of video stream used in
20+
* the {@link MediaItem}.
21+
**/
1422
public final class StreamInfoTag implements MediaItemTag {
1523
@NonNull
1624
private final StreamInfo streamInfo;

app/src/main/java/org/schabi/newpipe/player/mediasource/FailedMediaSource.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,15 @@
2323
import androidx.annotation.Nullable;
2424

2525
public class FailedMediaSource extends CompositeMediaSource<Void> implements ManagedMediaSource {
26-
private static final long SILENCE_DURATION_US = TimeUnit.SECONDS.toMicros(2);
26+
/**
27+
* Play 2 seconds of silenced audio when a stream fails to resolve due to a known issue,
28+
* such as {@link org.schabi.newpipe.extractor.exceptions.ExtractionException}.
29+
*
30+
* This silence duration allows user to react and have time to jump to a previous stream,
31+
* while still provide a smooth playback experience. A duration lower than 1 second is
32+
* not recommended, it may cause ExoPlayer to buffer for a while.
33+
* */
34+
public static final long SILENCE_DURATION_US = TimeUnit.SECONDS.toMicros(2);
2735

2836
private final String TAG = "FailedMediaSource@" + Integer.toHexString(hashCode());
2937
private final PlayQueueItem playQueueItem;
@@ -32,7 +40,7 @@ public class FailedMediaSource extends CompositeMediaSource<Void> implements Man
3240
private final MediaSource source;
3341
private final MediaItem mediaItem;
3442
/**
35-
* Permanently fail the play queue item associated with this source, with no hope of retrying.
43+
* Fail the play queue item associated with this source, with potential future retries.
3644
*
3745
* The error will be propagated if the cause for load exception is unspecified.
3846
* This means the error might be caused by reasons outside of extraction (e.g. no network).

0 commit comments

Comments
 (0)