Skip to content

Commit dfc46c3

Browse files
committed
Support audio only background for services only supporting video streams
Some services may only have video streams and no separate audio streams available. This commit will add audio background playback support for those services. It uses the video source as audio source for background playback.
1 parent 5942add commit dfc46c3

2 files changed

Lines changed: 56 additions & 6 deletions

File tree

app/src/main/java/org/schabi/newpipe/player/resolver/AudioPlaybackResolver.java

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
import com.google.android.exoplayer2.source.MediaSource;
1212

1313
import org.schabi.newpipe.extractor.stream.AudioStream;
14+
import org.schabi.newpipe.extractor.stream.Stream;
1415
import org.schabi.newpipe.extractor.stream.StreamInfo;
16+
import org.schabi.newpipe.extractor.stream.VideoStream;
1517
import org.schabi.newpipe.player.helper.PlayerDataSource;
1618
import org.schabi.newpipe.player.mediaitem.MediaItemTag;
1719
import org.schabi.newpipe.player.mediaitem.StreamInfoTag;
@@ -41,22 +43,50 @@ public MediaSource resolve(@NonNull final StreamInfo info) {
4143
return liveSource;
4244
}
4345

44-
final List<AudioStream> audioStreams = getNonTorrentStreams(info.getAudioStreams());
45-
46-
final int index = ListHelper.getDefaultAudioFormat(context, audioStreams);
47-
if (index < 0 || index >= info.getAudioStreams().size()) {
46+
final Stream stream = getAudioSource(info);
47+
if (stream == null) {
4848
return null;
4949
}
5050

51-
final AudioStream audio = info.getAudioStreams().get(index);
5251
final MediaItemTag tag = StreamInfoTag.of(info);
5352

5453
try {
5554
return PlaybackResolver.buildMediaSource(
56-
dataSource, audio, info, PlaybackResolver.cacheKeyOf(info, audio), tag);
55+
dataSource, stream, info, PlaybackResolver.cacheKeyOf(info, stream), tag);
5756
} catch (final ResolverException e) {
5857
Log.e(TAG, "Unable to create audio source", e);
5958
return null;
6059
}
6160
}
61+
62+
/**
63+
* Get a stream to be played as audio. If a service has no separate {@link AudioStream}s we
64+
* use a video stream as audio source to support audio background playback.
65+
*
66+
* @param info of the stream
67+
* @return the audio source to use or null if none could be found
68+
*/
69+
@Nullable
70+
private Stream getAudioSource(@NonNull final StreamInfo info) {
71+
final List<AudioStream> audioStreams = getNonTorrentStreams(info.getAudioStreams());
72+
if (!audioStreams.isEmpty()) {
73+
final int index = ListHelper.getDefaultAudioFormat(context, audioStreams);
74+
return getStreamForIndex(index, audioStreams);
75+
} else {
76+
final List<VideoStream> videoStreams = getNonTorrentStreams(info.getVideoStreams());
77+
if (!videoStreams.isEmpty()) {
78+
final int index = ListHelper.getDefaultResolutionIndex(context, videoStreams);
79+
return getStreamForIndex(index, videoStreams);
80+
}
81+
}
82+
return null;
83+
}
84+
85+
@Nullable
86+
Stream getStreamForIndex(final int index, @NonNull final List<? extends Stream> streams) {
87+
if (index >= 0 && index < streams.size()) {
88+
return streams.get(index);
89+
}
90+
return null;
91+
}
6292
}

app/src/main/java/org/schabi/newpipe/player/resolver/PlaybackResolver.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,26 @@ static String cacheKeyOf(final StreamInfo info, final AudioStream audioStream) {
158158

159159
return cacheKey.toString();
160160
}
161+
162+
/**
163+
* Use common base type {@link Stream} to handle {@link AudioStream} or {@link VideoStream}
164+
* transparently. For more info see {@link #cacheKeyOf(StreamInfo, AudioStream)} or
165+
* {@link #cacheKeyOf(StreamInfo, VideoStream)}.
166+
*
167+
* @param info the {@link StreamInfo stream info}, to distinguish between streams with
168+
* the same features but coming from different stream infos
169+
* @param stream the {@link Stream} ({@link AudioStream} or {@link VideoStream})
170+
* for which the cache key should be created
171+
* @return a key to be used to store the cache of the provided {@link Stream}
172+
*/
173+
static String cacheKeyOf(final StreamInfo info, final Stream stream) {
174+
if (stream instanceof AudioStream) {
175+
return cacheKeyOf(info, (AudioStream) stream);
176+
} else if (stream instanceof VideoStream) {
177+
return cacheKeyOf(info, (VideoStream) stream);
178+
}
179+
throw new RuntimeException("no audio or video stream. That should never happen");
180+
}
161181
//endregion
162182

163183

0 commit comments

Comments
 (0)