Resolver: Cleaned up ``isVideoStreamVideoOnly``

* Replaced by ``wasLastResolvedVideoAndAudioSeparated``
* Uses an ``Optional`` instead (we can't determine if the video and audio streams are separated when we did not fetch it)
This commit is contained in:
litetex 2021-11-16 21:40:18 +01:00 committed by TiA4f8R
parent a489f40b76
commit bb27bf9d34
No known key found for this signature in database
GPG Key ID: E6D3E7F5949450DD
4 changed files with 88 additions and 82 deletions

View File

@ -3293,7 +3293,8 @@ public final class Player implements
if (audioPlayerSelected()) {
return audioResolver.resolve(info);
} else {
if (isAudioOnly && !videoResolver.isVideoStreamVideoOnly()) {
if (isAudioOnly
&& !videoResolver.wasLastResolvedVideoAndAudioSeparated().orElse(false)) {
return audioResolver.resolve(info);
}
@ -4189,8 +4190,9 @@ public final class Player implements
final boolean isVideoStreamTypeAndIsVideoOnlyStreamOrNoAudioStreamsAvailable =
(streamType == StreamType.VIDEO_STREAM || streamType == StreamType.LIVE_STREAM)
&& (videoResolver.isVideoStreamVideoOnly()
&& (videoResolver.wasLastResolvedVideoAndAudioSeparated().orElse(false)
|| isNullOrEmpty(info.getAudioStreams()));
if (videoRenderIndex != RENDERER_UNAVAILABLE
&& isVideoStreamTypeAndIsVideoOnlyStreamOrNoAudioStreamsAvailable) {
final TrackGroupArray videoTrackGroupArray = Objects.requireNonNull(

View File

@ -44,9 +44,4 @@ public class AudioPlaybackResolver implements PlaybackResolver {
return buildMediaSource(dataSource, audio.getUrl(), PlayerHelper.cacheKeyOf(info, audio),
MediaFormat.getSuffixById(audio.getFormatId()), tag);
}
@Override
public boolean isVideoStreamVideoOnly() {
return false;
}
}

View File

@ -6,6 +6,4 @@ import androidx.annotation.Nullable;
public interface Resolver<Source, Product> {
@Nullable
Product resolve(@NonNull Source source);
boolean isVideoStreamVideoOnly();
}

View File

@ -21,6 +21,7 @@ import org.schabi.newpipe.util.ListHelper;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import static com.google.android.exoplayer2.C.TIME_UNSET;
@ -35,7 +36,7 @@ public class VideoPlaybackResolver implements PlaybackResolver {
@Nullable
private String playbackQuality;
private boolean isVideoStreamVideoOnly = false;
private Boolean wasLastResolvedVideoAndAudioSeparated;
public VideoPlaybackResolver(@NonNull final Context context,
@NonNull final PlayerDataSource dataSource,
@ -48,83 +49,93 @@ public class VideoPlaybackResolver implements PlaybackResolver {
@Override
@Nullable
public MediaSource resolve(@NonNull final StreamInfo info) {
isVideoStreamVideoOnly = false;
final MediaSource liveSource = maybeBuildLiveMediaSource(dataSource, info);
if (liveSource != null) {
return liveSource;
}
final List<MediaSource> mediaSources = new ArrayList<>();
// Create video stream source
final List<VideoStream> videos = ListHelper.getSortedStreamVideosList(context,
info.getVideoStreams(), info.getVideoOnlyStreams(), false, true);
final int index;
if (videos.isEmpty()) {
index = -1;
} else if (playbackQuality == null) {
index = qualityResolver.getDefaultResolutionIndex(videos);
} else {
index = qualityResolver.getOverrideResolutionIndex(videos, getPlaybackQuality());
}
final MediaSourceTag tag = new MediaSourceTag(info, videos, index);
@Nullable final VideoStream video = tag.getSelectedVideoStream();
if (video != null) {
final MediaSource streamSource = buildMediaSource(dataSource, video.getUrl(),
PlayerHelper.cacheKeyOf(info, video),
MediaFormat.getSuffixById(video.getFormatId()), tag);
mediaSources.add(streamSource);
}
// Create optional audio stream source
final List<AudioStream> audioStreams = info.getAudioStreams();
final AudioStream audio = audioStreams.isEmpty() ? null : audioStreams.get(
ListHelper.getDefaultAudioFormat(context, audioStreams));
// Use the audio stream if there is no video stream, or
// Merge with audio stream in case if video does not contain audio
if (audio != null && (video == null || video.isVideoOnly)) {
final MediaSource audioSource = buildMediaSource(dataSource, audio.getUrl(),
PlayerHelper.cacheKeyOf(info, audio),
MediaFormat.getSuffixById(audio.getFormatId()), tag);
mediaSources.add(audioSource);
isVideoStreamVideoOnly = true;
}
// If there is no audio or video sources, then this media source cannot be played back
if (mediaSources.isEmpty()) {
return null;
}
// Below are auxiliary media sources
// Create subtitle sources
if (info.getSubtitles() != null) {
for (final SubtitlesStream subtitle : info.getSubtitles()) {
final String mimeType = PlayerHelper.subtitleMimeTypesOf(subtitle.getFormat());
if (mimeType == null) {
continue;
}
final MediaSource textSource = dataSource.getSampleMediaSourceFactory()
.createMediaSource(
new MediaItem.Subtitle(Uri.parse(subtitle.getUrl()),
mimeType,
PlayerHelper.captionLanguageOf(context, subtitle)),
TIME_UNSET);
mediaSources.add(textSource);
boolean isVideoAndAudioSeparated = false;
try {
final MediaSource liveSource = maybeBuildLiveMediaSource(dataSource, info);
if (liveSource != null) {
return liveSource;
}
}
if (mediaSources.size() == 1) {
return mediaSources.get(0);
} else {
return new MergingMediaSource(mediaSources.toArray(
new MediaSource[0]));
final List<MediaSource> mediaSources = new ArrayList<>();
// Create video stream source
final List<VideoStream> videos = ListHelper.getSortedStreamVideosList(context,
info.getVideoStreams(), info.getVideoOnlyStreams(), false, true);
final int index;
if (videos.isEmpty()) {
index = -1;
} else if (playbackQuality == null) {
index = qualityResolver.getDefaultResolutionIndex(videos);
} else {
index = qualityResolver.getOverrideResolutionIndex(videos, getPlaybackQuality());
}
final MediaSourceTag tag = new MediaSourceTag(info, videos, index);
@Nullable final VideoStream video = tag.getSelectedVideoStream();
if (video != null) {
final MediaSource streamSource = buildMediaSource(dataSource, video.getUrl(),
PlayerHelper.cacheKeyOf(info, video),
MediaFormat.getSuffixById(video.getFormatId()), tag);
mediaSources.add(streamSource);
}
// Create optional audio stream source
final List<AudioStream> audioStreams = info.getAudioStreams();
final AudioStream audio = audioStreams.isEmpty() ? null : audioStreams.get(
ListHelper.getDefaultAudioFormat(context, audioStreams));
// Use the audio stream if there is no video stream, or
// Merge with audio stream in case if video does not contain audio
if (audio != null && (video == null || video.isVideoOnly)) {
final MediaSource audioSource = buildMediaSource(dataSource, audio.getUrl(),
PlayerHelper.cacheKeyOf(info, audio),
MediaFormat.getSuffixById(audio.getFormatId()), tag);
mediaSources.add(audioSource);
isVideoAndAudioSeparated = true;
}
// If there is no audio or video sources, then this media source cannot be played back
if (mediaSources.isEmpty()) {
return null;
}
// Below are auxiliary media sources
// Create subtitle sources
if (info.getSubtitles() != null) {
for (final SubtitlesStream subtitle : info.getSubtitles()) {
final String mimeType = PlayerHelper.subtitleMimeTypesOf(subtitle.getFormat());
if (mimeType == null) {
continue;
}
final MediaSource textSource = dataSource.getSampleMediaSourceFactory()
.createMediaSource(
new MediaItem.Subtitle(Uri.parse(subtitle.getUrl()),
mimeType,
PlayerHelper.captionLanguageOf(context, subtitle)),
TIME_UNSET);
mediaSources.add(textSource);
}
}
if (mediaSources.size() == 1) {
return mediaSources.get(0);
} else {
return new MergingMediaSource(mediaSources.toArray(
new MediaSource[0]));
}
} finally {
wasLastResolvedVideoAndAudioSeparated = isVideoAndAudioSeparated;
}
}
@Override
public boolean isVideoStreamVideoOnly() {
return isVideoStreamVideoOnly;
/**
* Determines if the last resolved StreamInfo had separated audio and video streams
* (or only audio).
*
* @return {@link Optional#empty()} if nothing was resolved
* otherwise <code>true</code> or <code>false</code>
*/
public Optional<Boolean> wasLastResolvedVideoAndAudioSeparated() {
return Optional.ofNullable(wasLastResolvedVideoAndAudioSeparated);
}
@Nullable