Move stream's cache key generation in PlaybackResolver and improve PlaybackResolver's code

This commit is contained in:
Stypox 2022-05-08 14:39:24 +02:00 committed by AudricV
parent fbee310261
commit ef20d9b91a
No known key found for this signature in database
GPG Key ID: DA92EC7905614198
4 changed files with 79 additions and 54 deletions

View File

@ -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.

View File

@ -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;

View File

@ -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) {

View File

@ -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) {