Move stream's cache key generation in PlaybackResolver and improve PlaybackResolver's code
This commit is contained in:
parent
fbee310261
commit
ef20d9b91a
|
@ -3,8 +3,6 @@ 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.extractor.stream.AudioStream.UNKNOWN_BITRATE;
|
||||
import static org.schabi.newpipe.extractor.stream.VideoStream.RESOLUTION_UNKNOWN;
|
||||
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;
|
||||
|
@ -47,11 +45,9 @@ import com.google.android.exoplayer2.util.MimeTypes;
|
|||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.extractor.InfoItem;
|
||||
import org.schabi.newpipe.extractor.MediaFormat;
|
||||
import org.schabi.newpipe.extractor.stream.AudioStream;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||
import org.schabi.newpipe.extractor.stream.SubtitlesStream;
|
||||
import org.schabi.newpipe.extractor.stream.VideoStream;
|
||||
import org.schabi.newpipe.extractor.utils.Utils;
|
||||
import org.schabi.newpipe.player.MainPlayer;
|
||||
import org.schabi.newpipe.player.Player;
|
||||
|
@ -197,52 +193,6 @@ public final class PlayerHelper {
|
|||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static String cacheKeyOf(@NonNull final StreamInfo info,
|
||||
@NonNull final VideoStream videoStream) {
|
||||
String cacheKey = info.getUrl() + " " + videoStream.getId();
|
||||
|
||||
final String resolution = videoStream.getResolution();
|
||||
final MediaFormat mediaFormat = videoStream.getFormat();
|
||||
if (resolution.equals(RESOLUTION_UNKNOWN) && mediaFormat == null) {
|
||||
// The hash code is only used in the cache key in the case when the resolution and the
|
||||
// media format are unknown
|
||||
cacheKey += " " + videoStream.hashCode();
|
||||
} else {
|
||||
if (mediaFormat != null) {
|
||||
cacheKey += " " + videoStream.getFormat().getName();
|
||||
}
|
||||
if (!resolution.equals(RESOLUTION_UNKNOWN)) {
|
||||
cacheKey += " " + resolution;
|
||||
}
|
||||
}
|
||||
|
||||
return cacheKey;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static String cacheKeyOf(@NonNull final StreamInfo info,
|
||||
@NonNull final AudioStream audioStream) {
|
||||
String cacheKey = info.getUrl() + " " + audioStream.getId();
|
||||
|
||||
final int averageBitrate = audioStream.getAverageBitrate();
|
||||
final MediaFormat mediaFormat = audioStream.getFormat();
|
||||
if (averageBitrate == UNKNOWN_BITRATE && mediaFormat == null) {
|
||||
// The hash code is only used in the cache key in the case when the resolution and the
|
||||
// media format are unknown
|
||||
cacheKey += " " + audioStream.hashCode();
|
||||
} else {
|
||||
if (mediaFormat != null) {
|
||||
cacheKey += " " + audioStream.getFormat().getName();
|
||||
}
|
||||
if (averageBitrate != UNKNOWN_BITRATE) {
|
||||
cacheKey += " " + averageBitrate;
|
||||
}
|
||||
}
|
||||
|
||||
return cacheKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a {@link StreamInfo} and the existing queue items,
|
||||
* provide the {@link SinglePlayQueue} consisting of the next video for auto queueing.
|
||||
|
|
|
@ -13,7 +13,6 @@ import com.google.android.exoplayer2.source.MediaSource;
|
|||
import org.schabi.newpipe.extractor.stream.AudioStream;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
import org.schabi.newpipe.player.helper.PlayerDataSource;
|
||||
import org.schabi.newpipe.player.helper.PlayerHelper;
|
||||
import org.schabi.newpipe.player.mediaitem.MediaItemTag;
|
||||
import org.schabi.newpipe.player.mediaitem.StreamInfoTag;
|
||||
import org.schabi.newpipe.util.ListHelper;
|
||||
|
@ -57,7 +56,7 @@ public class AudioPlaybackResolver implements PlaybackResolver {
|
|||
|
||||
try {
|
||||
return PlaybackResolver.buildMediaSource(
|
||||
dataSource, audio, info, PlayerHelper.cacheKeyOf(info, audio), tag);
|
||||
dataSource, audio, info, PlaybackResolver.cacheKeyOf(info, audio), tag);
|
||||
} catch (final IOException e) {
|
||||
Log.e(TAG, "Unable to create audio source:", e);
|
||||
return null;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.schabi.newpipe.player.resolver;
|
||||
|
||||
import static org.schabi.newpipe.extractor.stream.AudioStream.UNKNOWN_BITRATE;
|
||||
import static org.schabi.newpipe.extractor.stream.VideoStream.RESOLUTION_UNKNOWN;
|
||||
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
|
||||
import static org.schabi.newpipe.player.helper.PlayerDataSource.LIVE_STREAM_EDGE_GAP_MILLIS;
|
||||
|
||||
|
@ -20,6 +22,7 @@ import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource;
|
|||
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest;
|
||||
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifestParser;
|
||||
|
||||
import org.schabi.newpipe.extractor.MediaFormat;
|
||||
import org.schabi.newpipe.extractor.ServiceList;
|
||||
import org.schabi.newpipe.extractor.services.youtube.ItagItem;
|
||||
import org.schabi.newpipe.extractor.services.youtube.dashmanifestcreators.CreationException;
|
||||
|
@ -49,6 +52,79 @@ import java.util.Objects;
|
|||
public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
|
||||
String TAG = PlaybackResolver.class.getSimpleName();
|
||||
|
||||
@NonNull
|
||||
private static StringBuilder commonCacheKeyOf(@NonNull final StreamInfo info,
|
||||
@NonNull final Stream stream,
|
||||
final boolean resolutionOrBitrateUnknown) {
|
||||
// stream info service id
|
||||
final StringBuilder cacheKey = new StringBuilder(info.getServiceId());
|
||||
|
||||
// stream info id
|
||||
cacheKey.append(" ");
|
||||
cacheKey.append(info.getId());
|
||||
|
||||
// stream id (even if unknown)
|
||||
cacheKey.append(" ");
|
||||
cacheKey.append(stream.getId());
|
||||
|
||||
// mediaFormat (if not null)
|
||||
final MediaFormat mediaFormat = stream.getFormat();
|
||||
if (mediaFormat != null) {
|
||||
cacheKey.append(" ");
|
||||
cacheKey.append(mediaFormat.getName());
|
||||
}
|
||||
|
||||
// content (only if other information is missing)
|
||||
// If the media format and the resolution/bitrate are both missing, then we don't have
|
||||
// enough information to distinguish this stream from other streams.
|
||||
// So, only in that case, we use the content (i.e. url or manifest) to differentiate
|
||||
// between streams.
|
||||
// Note that if the content were used even when other information is present, then two
|
||||
// streams with the same stats but with different contents (e.g. because the url was
|
||||
// refreshed) will be considered different (i.e. with a different cacheKey), making the
|
||||
// cache useless.
|
||||
if (resolutionOrBitrateUnknown && mediaFormat == null) {
|
||||
cacheKey.append(" ");
|
||||
Objects.hash(stream.getContent(), stream.getManifestUrl());
|
||||
}
|
||||
|
||||
return cacheKey;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
static String cacheKeyOf(@NonNull final StreamInfo info,
|
||||
@NonNull final VideoStream videoStream) {
|
||||
final boolean resolutionUnknown = videoStream.getResolution().equals(RESOLUTION_UNKNOWN);
|
||||
final StringBuilder cacheKey = commonCacheKeyOf(info, videoStream, resolutionUnknown);
|
||||
|
||||
// resolution (if known)
|
||||
if (!resolutionUnknown) {
|
||||
cacheKey.append(" ");
|
||||
cacheKey.append(videoStream.getResolution());
|
||||
}
|
||||
|
||||
// isVideoOnly
|
||||
cacheKey.append(" ");
|
||||
cacheKey.append(videoStream.isVideoOnly());
|
||||
|
||||
return cacheKey.toString();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
static String cacheKeyOf(@NonNull final StreamInfo info,
|
||||
@NonNull final AudioStream audioStream) {
|
||||
final boolean averageBitrateUnknown = audioStream.getAverageBitrate() == UNKNOWN_BITRATE;
|
||||
final StringBuilder cacheKey = commonCacheKeyOf(info, audioStream, averageBitrateUnknown);
|
||||
|
||||
// averageBitrate (if known)
|
||||
if (!averageBitrateUnknown) {
|
||||
cacheKey.append(" ");
|
||||
cacheKey.append(audioStream.getAverageBitrate());
|
||||
}
|
||||
|
||||
return cacheKey.toString();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static MediaSource maybeBuildLiveMediaSource(@NonNull final PlayerDataSource dataSource,
|
||||
@NonNull final StreamInfo info) {
|
||||
|
|
|
@ -95,7 +95,7 @@ public class VideoPlaybackResolver implements PlaybackResolver {
|
|||
if (video != null) {
|
||||
try {
|
||||
final MediaSource streamSource = PlaybackResolver.buildMediaSource(
|
||||
dataSource, video, info, PlayerHelper.cacheKeyOf(info, video), tag);
|
||||
dataSource, video, info, PlaybackResolver.cacheKeyOf(info, video), tag);
|
||||
mediaSources.add(streamSource);
|
||||
} catch (final IOException e) {
|
||||
Log.e(TAG, "Unable to create video source:", e);
|
||||
|
@ -114,7 +114,7 @@ public class VideoPlaybackResolver implements PlaybackResolver {
|
|||
if (audio != null && (video == null || video.isVideoOnly())) {
|
||||
try {
|
||||
final MediaSource audioSource = PlaybackResolver.buildMediaSource(
|
||||
dataSource, audio, info, PlayerHelper.cacheKeyOf(info, audio), tag);
|
||||
dataSource, audio, info, PlaybackResolver.cacheKeyOf(info, audio), tag);
|
||||
mediaSources.add(audioSource);
|
||||
streamSourceType = SourceType.VIDEO_WITH_SEPARATED_AUDIO;
|
||||
} catch (final IOException e) {
|
||||
|
|
Loading…
Reference in New Issue